Framework for looking up contacts directly in nepomuk in addition to going through...
[kdepim.git] / messageviewer / spamheaderanalyzer.cpp
blob683e1414b0b69404d0e56fe0c9735453a5fd23eb
1 /* -*- mode: C++; c-file-style: "gnu" -*-
2 spamheaderanalyzer.cpp
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2004 Patrick Audley <paudley@blackcat.ca>
6 Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org>
8 KMail is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 KMail is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 In addition, as a special exception, the copyright holders give
23 permission to link the code of this program with any edition of
24 the Qt library by Trolltech AS, Norway (or with modified versions
25 of Qt that use the same license as Qt), and distribute linked
26 combinations including the two. You must obey the GNU General
27 Public License in all respects for all of the code used other than
28 Qt. If you modify this file, you may extend this exception to
29 your version of the file, but you are not obligated to do so. If
30 you do not wish to do so, delete this exception statement from
31 your version.
35 #include <config-messageviewer.h>
37 #include "spamheaderanalyzer.h"
39 #include "antispamconfig.h"
41 #include <kmime/kmime_message.h>
42 #include <kmime/kmime_headers.h>
44 #include <kdebug.h>
46 #include <boost/shared_ptr.hpp>
48 using namespace MessageViewer;
50 // static
51 SpamScores SpamHeaderAnalyzer::getSpamScores( KMime::Message *message ) {
52 SpamScores scores;
53 const SpamAgents agents = AntiSpamConfig::instance()->uniqueAgents();
54 SpamAgents::const_iterator end( agents.end() );
55 for ( SpamAgents::const_iterator it = agents.begin(); it != end; ++it ) {
56 float score = -2.0;
58 SpamError spamError = noError;
60 // Skip bogus agents
61 if ( (*it).scoreType() == SpamAgentNone )
62 continue;
64 // Do we have the needed score field for this agent?
65 KMime::Headers::Base *header= message->headerByType( (*it).header() );
66 if ( !header )
67 continue;
69 const QString mField = header->asUnicodeString();
71 if ( mField.isEmpty() )
72 continue;
74 QString scoreString;
75 bool scoreValid = false;
77 if ( (*it).scoreType() != SpamAgentBool ) {
78 // Can we extract the score?
79 QRegExp scorePattern = (*it).scorePattern();
80 if ( scorePattern.indexIn( mField ) != -1 ) {
81 scoreString = scorePattern.cap( 1 );
82 scoreValid = true;
84 } else
85 scoreValid = true;
87 if ( !scoreValid ) {
88 spamError = couldNotFindTheScoreField;
89 kDebug() << "Score could not be extracted from header '"
90 << mField << "'";
91 } else {
92 bool floatValid = false;
93 switch ( (*it).scoreType() ) {
94 case SpamAgentNone:
95 spamError = errorExtractingAgentString;
96 break;
98 case SpamAgentBool:
99 if( (*it).scorePattern().indexIn( mField ) == -1 )
100 score = 0.0;
101 else
102 score = 100.0;
103 break;
105 case SpamAgentFloat:
106 score = scoreString.toFloat( &floatValid );
107 if ( !floatValid ) {
108 spamError = couldNotConverScoreToFloat;
109 kDebug() << "Score (" << scoreString << ") is no number";
111 else
112 score *= 100.0;
113 break;
115 case SpamAgentFloatLarge:
116 score = scoreString.toFloat( &floatValid );
117 if ( !floatValid ) {
118 spamError = couldNotConverScoreToFloat;
119 kDebug() << "Score (" << scoreString << ") is no number";
121 break;
123 case SpamAgentAdjustedFloat:
124 score = scoreString.toFloat( &floatValid );
125 if ( !floatValid ) {
126 spamError = couldNotConverScoreToFloat;
127 kDebug() << "Score (" << scoreString << ") is no number";
128 break;
131 // Find the threshold value.
132 QString thresholdString;
133 QRegExp thresholdPattern = (*it).thresholdPattern();
134 if ( thresholdPattern.indexIn( mField ) != -1 ) {
135 thresholdString = thresholdPattern.cap( 1 );
137 else {
138 spamError = couldNotFindTheThresholdField;
139 kDebug() << "Threshold could not be extracted from header '"
140 << mField << "'";
141 break;
143 float threshold = thresholdString.toFloat( &floatValid );
144 if ( !floatValid || ( threshold <= 0.0 ) ) {
145 spamError = couldNotConvertThresholdToFloatOrThresholdIsNegative;
146 kDebug() << "Threshold (" << thresholdString << ") is no"
147 << "number or is negative";
148 break;
151 // Normalize the score. Anything below 0 means 0%, anything above
152 // threshold mean 100%. Values between 0 and threshold are mapped
153 // linearily to 0% - 100%.
154 if ( score < 0.0 )
155 score = 0.0;
156 else if ( score > threshold )
157 score = 100.0;
158 else
159 score = score / threshold * 100.0;
160 break;
163 //Find the confidence
164 float confidence = -2.0;
165 QString confidenceString = "-2.0";
166 bool confidenceValid = false;
167 // Do we have the needed confidence field for this agent?
168 QByteArray confidenceHeaderName = (*it).confidenceHeader();
169 QString mCField;
170 if( !confidenceHeaderName.isEmpty() )
172 KMime::Headers::Base *cHeader = message->headerByType( confidenceHeaderName );
173 if ( cHeader )
175 mCField = cHeader->asUnicodeString();
176 if ( ! mCField.isEmpty() ) {
177 // Can we extract the confidence?
178 QRegExp cScorePattern = (*it).confidencePattern();
179 if ( cScorePattern.indexIn( mCField ) != -1 ) {
180 confidenceString = cScorePattern.cap( 1 );
182 confidence = confidenceString.toFloat( &confidenceValid );
183 if( !confidenceValid) {
184 spamError = couldNotConvertConfidenceToFloat;
185 kDebug() << "Unable to convert confidence to float:" << confidenceString;
190 scores.append( SpamScore( (*it).name(), spamError, score, confidence*100, mField, mCField ) );
193 return scores;