1=head1 NAME 2 3cm_perl -- A Perl Plugin for Claws Mail 4 5=head1 DESCRIPTION 6 7This plugin provides an extended filtering engine for the email 8client Claws Mail. It allows for the use of full Perl power 9in email filters. 10 11=head1 QUICK START 12 13To get started, you can use the B<matcherrc2perlfilter.pl> script 14in the B<tools>-directory to translate your old filtering rules to 15Perl. Simply execute the script and follow the instructions. 16(note that with recent versions of Claws Mail, this script might not 17work due to upstream syntax changes. This will get updated in the 18future. Send me an email if you have problems getting started). 19 20However, you might want to consider reading the rest of this 21manual and rewriting your rules if you choose to use the plugin, 22since the Perl code produced by this script is not exactly 23pretty. 24 25Don't speak Perl? No problem, L<"perldoc perlintro"|perlintro> 26should give you enough information to do fancy stuff. 27 28=head1 USAGE 29 30The Perl plugin expects a Perl script file called B<perl_filter> 31in Claws Mail' config directory (usually $HOME/.claws-mail -- 32try `claws-mail --config-dir' if you're unsure). If that file 33doesn't exist on plugin start, an empty one is created. This 34file, which doesn't need to start with a sha-bang (!#/bin/perl), 35holds the Perl instructions for your email filters. To encourage 36some good manners, the code is executed in a C<use strict;> 37environment. 38 39Both Claws Mail' filtering B<conditions> and B<actions> are 40mapped to Perl functions with corresponding names, wherever this 41is possible. 42 43=head1 FUNCTION LISTING 44 45For a detailed function description, see section L</"FUNCTION 46DESCRIPTIONS">, below. 47 48=over 4 49 50=item Standard Filtering Conditions 51 52 all, marked, unread, deleted, new, replied, 53 forwarded, locked, ignore_thread, colorlabel, 54 match, matchcase, regexp, S<regexpcase, test, 55 size_greater, size_smaller, size_equal, 56 score_greater, score_lower, score_equal, age_greater, 57 age_lower, partial, tagged 58 59=item Standard Filtering Actions 60 61 mark, unmark, dele, mark_as_unread, mark_as_read, 62 lock, unlock, move, copy, color, execute, 63 hide, set_score, change_score, stop, forward, 64 forward_as_attachment, redirect, set_tag, unset_tag, 65 clear_tags 66 67=item Fun stuff 68 69 header, body, filepath, extract_addresses, 70 move_to_trash, abort, addr_in_addressbook, 71 from_in_addressbook, get_attribute_value, SA_is_spam, 72 exit, manual, make_sure_folder_exists, 73 filter_log, filter_log_verbosity, 74 make_sure_tag_exists 75 76=back 77 78=head1 FUNCTION DESCRIPTIONS 79 80In general, after the filtering invoked by the Perl script, the 81mail is passed on to Claws' internal filtering engine, I<unless> 82a B<final> rule was hit. Final rules stop not only the Perl 83filtering script at the point of their occurrence, but also 84prevent processing that email by Claws' internal filtering engine 85(this might sound confusing, but you are already familiar with 86that concept from standard filters: After an email was 87e.g. I<move>d, the following rules don't apply anymore). 88 89Also, be careful with the way you quote. In particular, remember 90that the @-sign has a special meaning in Perl, and gets 91interpolated inside double quotes. See L<perlop/"Quote and 92Quote-like Operators"> to learn more about quoting and 93interpolation. 94 95 96=head2 Standard Filtering Conditions 97 98=over 8 99 100=item all 101 102Returns a true value. Available for completeness only. 103 104=item marked 105 106Returns a true value if the marked flag is set, false otherwise. 107 108=item unread 109 110Returns a true value if the unread flag is set, false otherwise. 111 112=item deleted 113 114Returns a true value if the deleted flag is set, false otherwise. 115 116=item new 117 118Returns a true value if the new flag is set, false otherwise. 119 120=item replied 121 122Returns a true value if the replied flag is set, false otherwise. 123 124=item forwarded 125 126Returns a true value if the forwarded flag is set, false otherwise. 127 128=item locked 129 130Returns a true value if the locked flag is set, false otherwise. 131 132=item ignore_thread 133 134Returns a true value if the "Ignore Thread" flag is set, false otherwise. 135 136=item colorlabel COLOR 137 138=item colorlabel 139 140Returns a true value if message has the color COLOR. COLOR can be 141either a numeric value between 0 and 7 (with colors corresponding 142to the internal filtering engine), or the english color name as 143it is introduced in the filtering dialog (that is, one of: none, 144orange, red, pink, sky blue, blue, green or brown, while upper 145and lower case letters make no difference). If COLOR is omitted, 1460 (none) is assumed. 147 148=item size_greater SIZE 149 150Returns a true value if message size is greater than SIZE, false otherwise. 151 152=item size_smaller SIZE 153 154Returns a true value if message size is smaller than SIZE, false otherwise. 155 156=item size_equal SIZE 157 158Returns a true value if message size is equal to SIZE, false otherwise. 159 160=item score_greater SCORE 161 162Returns a true value if message score is greater than SCORE, false otherwise. 163 164=item score_lower SCORE 165 166Returns a true value if message score is lower than SCORE, false otherwise. 167 168=item score_equal SCORE 169 170Returns a true value if message score is equal to SCORE, false otherwise. 171 172=item age_greater AGE 173 174Returns a true value if message age is greater than AGE, false otherwise. 175 176=item age_lower AGE 177 178Returns a true value if message age is lower than AGE, false otherwise. 179 180=item partial 181 182Returns a true value if message has only partially been 183downloaded, false otherwise. 184 185=item tagged 186 187Returns a true value if the messages has one or more tags. 188 189=item test 190 191Corresponds the 'test' internal filtering rule. In particular, it 192accepts the same symbols, namely: 193 194=over 195 196=item %% 197 198% 199 200=item %s 201 202Subject 203 204=item %f 205 206From 207 208=item %t 209 210To 211 212=item %c 213 214Cc 215 216=item %d 217 218Date 219 220=item %i 221 222Message-ID 223 224=item %n 225 226Newsgroups 227 228=item %r 229 230References 231 232=item %F 233 234Filename -- should not be modified 235 236=back 237 238=item match WHERE WHAT 239 240=item matchcase WHERE WHAT 241 242=item regexp WHERE WHAT 243 244=item regexpcase WHERE WHAT 245 246The matching functions have a special syntax. The first argument 247is either any of to_or_cc, body_part, headers_part, headers_cont, 248message, to, from, subject, cc, newsgroups, inreplyto, 249references, or tag (those strings may or may not be quoted), the 250pattern matching works on that area. If it is any other string 251(which must then be quoted), this string is taken to be the name 252of a header field. 253 254The second argument is the string to look for. For match, 255matchcase, regexp and regexpcase we have case sensitive normal 256matching, case insensitive normal matching, case sensitive 257regular expression matching and case insensitive regular 258expression pattern matching, respectively. 259 260The functions return true if the pattern was found, false 261otherwise. 262 263Just as with the built-in filtering engine, the message body is 264searched and provided as is - no character-set analysis is 265done. Likewise, no HTML-tags are stripped. It should be possible 266to use external modules or programs for these tasks though. If 267you're doing that, drop me a message with your experiences. 268 269With Perl having its strengths in pattern matching, using Perl's 270builtin operators are usually a better option than using these 271functions. 272 273=back 274 275=head2 Standard Filtering Actions 276 277The actions return a true value upon success, and 'undef' when an 278error occurred. I<Final> message rules are indicated. (See above 279for a sketch what a final rule is) 280 281=over 8 282 283=item mark 284 285Mark the message. 286 287=item unmark 288 289Unmark the message. 290 291=item dele 292 293Delete the message. Note the name change of Claws Mail' 294"delete" to "dele". This is because "delete" is one of Perl's 295builtin commands which cannot be redefined (if it can, tell me 296how). 297 298This is a I<final> rule. 299 300=item mark_as_read 301 302Mark the message as read 303 304=item mark_as_unread 305 306Mark the message as unread 307 308=item lock 309 310Lock the message 311 312=item unlock 313 314Remove the message lock 315 316=item move DESTINATION 317 318Move the message to folder DESTINATION. The folder notation is 319the same that Claws Mail uses. You can copy & paste from the 320move dialog of the normal filtering, until you get a feeling for 321the notation. 322 323This is a I<final> rule. 324 325=item copy DESTINATION 326 327Copy the message to folder DESTINATION. The folder notation is 328the same that Claws Mail uses. You can copy & paste from the 329move dialog of the normal filtering, until you get a feeling for 330the notation. 331 332=item execute COMMAND 333 334This is the same as the test - rule from section L</"Standard 335Filtering Conditions"> execpt that it always returns a true 336value. 337 338=item hide 339 340Hide the message 341 342=item set_score SCORE 343 344Set message score to SCORE 345 346=item change_score SCORE 347 348Change message score by SCORE 349 350=item stop 351 352Stop Perl script at this point. Note that this is B<not> a final 353rule, meaning that the email gets passed on to the internal 354filtering engine. See "abort" below if you don't want that. 355 356=item forward ACCOUNT, EMAIL 357 358Forward the message to email address EMAIL, using the account ID 359ACCOUNT as sender account. So far, you have to create a rule 360in the normal filtering engine to find out that number. 361 362=item forward_as_attachment, ACCOUNT EMAIL 363 364Forward the message to email address EMAIL in an attachment, 365using the account ID ACCOUNT as sender account. So far, you 366have to create a rule in the normal filtering engine to find out 367that number. 368 369=item redirect ACCOUNT, EMAIL 370 371Redirect the message to EMAIL, using the account ID ACCOUNT as 372sender account. So far, you have to create a rule in the normal 373filtering engine to find out that number. 374 375=item set_tag TAG 376 377Apply tag TAG. TAG must exist. 378 379=item unset_tag TAG 380 381Unset tag TAG. 382 383=item clear_tags 384 385Clear all tags. 386 387=back 388 389=head2 Fun stuff 390 391=head3 Functions 392 393=over 8 394 395=item header ARG 396 397=item header 398 399If ARG is not given, returns a list of all header field names of 400the mail. 401 402If ARG is given, returns 'undef' if the header field ARG does not 403exist in the email. Otherwise, it returns 404 405=over 406 407=item in scalar context 408 409The value of the header field ARG. 410 411=item in list context 412 413A list of all available header field values. This is useful if a 414header field occurs more than once in an email (eg the Received - 415header). 416 417=back 418 419The header field "References" forms a special case. In a scalar context, 420it returns the first reference. In a list context, it returns a list of 421all references. 422 423=item body 424 425Returns the email body in a scalar. 426 427=item filepath 428 429Returns the file and path of the email that is currently filtered 430(corresponds to the %F arguemnt in the 'test' rule). 431 432=item extract_addresses 433 434Extracts email addresses from a string and gives back a list of 435addresses found. Currently an email address is found using the 436regular expression '[-.+\w]+\@[-.+\w]+'. This will not find all 437valid email addresses. Feel free to send me a better regexp. 438 439=item move_to_trash 440 441Move the email message to default trash folder. 442 443This is a I<final> rule. 444 445=item abort 446 447Stop Perl script at this point. 448 449In contrast to 'stop', this is a I<final> rule. 450 451=item addr_in_addressbook EMAIL, ADDRESSBOOK 452 453=item addr_in_addressbook EMAIL 454 455Returns a true value if the email address EMAIL is in the addressbook 456with the name ADDRESSBOOK. If ADDRESSBOOK is not given, returns 457true if the email address is in any addressbook. 458 459=item from_in_addressbook ADDRESSBOOK 460 461=item from_in_addressbook 462 463Checks if the email address found in the From-header is in 464addressbook ADDRESSBOOK (or any, if omitted). It is implemented 465as 466 467 my ($from) = extract_addresses(header("from")); 468 return 0 unless $from; 469 return addr_in_addressbook($from,@_); 470 471so the same restrictions as to extract_addresses apply. 472 473=item get_attribute_value EMAIL, ATTRIBUTE, ADDRESSBOOK 474 475=item get_attribute_value EMAIL, ATTRIBUTE 476 477Looks through the addressbook ADDRESSBOOK (or all addressbooks, 478if omitted) for a contact with the an email address EMAIL. If 479found, the function checks if this contact has a user attribute 480with name ATTRIBUTE. It returns the value of this attribute, or 481an empty string if it was not found. As usual, 'undef' is 482returned if an error occurred. 483 484=item SA_is_spam 485 486Is an alias to 487 488not test 'spamc -c < %F > /dev/null' 489 490=item exit 491 492Has been redefined to be an alias to 'stop'. You shouldn't use 493Perl's own 'exit' command, since it would exit Claws Mail. 494 495=item manual 496 497Returns a true value if the filter script was invoked manually, 498that is, via the Tools menu. 499 500=item make_sure_folder_exists IDENTIFIER 501 502Returns a true value if the folder with id IDENTIFIER (e.g. #mh/Mail/foo/bar) 503exists or could be created. 504 505=item make_sure_tag_exists TAG 506 507Returns a true value if the tag TAG exists or could be created. 508 509=item filter_log SECTION, TEXT 510 511=item filter_log TEXT 512 513Writes TEXT to the filter logfile. SECTION can be any of 514 515=over 516 517=item * 518 519"LOG_MANUAL" 520 521=item * 522 523"LOG_MATCH" 524 525=item * 526 527"LOG_ACTION" 528 529=back 530 531If the SECTION is omitted, "LOG_MANUAL" is assumed. 532 533=item filter_log_verbosity VERBOSITY 534 535=item filter_log_verbosity 536 537Changes the filter log verbosity for the current mail. VERBOSITY 538must be any of 539 540=over 2 541 542=item C<0> 543 544Be silent 545 546=item C<1> 547 548Log MANUAL type 549 550=item C<2> 551 552Log Action type 553 554=item C<3> 555 556Log MATCH type 557 558=back 559 560For the meaning of those numbers, read section L</"LOGGING">. If 561VERBOSITY is omitted, the filter logfile verbosity is not changed. 562 563This function returns the filter_log_verbosity number before the 564change (if any). 565 566=back 567 568=head3 Variables 569 570=over 8 571 572=item $permanent 573 574This scalar keeps its value between filtered mail messages. On 575plugin start, it is initialized to the empty string. 576 577=back 578 579=head1 LOGGING 580 581To keep track of what has been done to the mails while filtering, 582the plugin supports logging. Three verbosity levels are 583recognized: 584 585=over 586 587=item C<0> 588 589logging disabled 590 591=item C<1> 592 593log only manual messages, that is, messages introduced by the 594C<filter_log> command in filter scripts 595 596=item C<2> 597 598log manual messages and filter actions 599 600=item C<3> 601 602log manual messages, filter actions and filter matches 603 604=back 605 606The messages are logged in Claws Mail' log window. 607The default log level is 2. Log level 3 is not 608recommended, because the matcher functions log a message if they 609succeeded, and thus, if you have negative checks, you'll get 610confusing entries. If you want to keep track of matching, do it 611manually, using C<filter_log>, or do it by temporary enabling 612matcher logging using C<filter_log_verbosity>. 613 614The first time you unload this plugin (or shut down 615Claws Mail), a section called B<[PerlPlugin]> will be created 616in Claws Mail' configuration file B<clawsrc>, containing 617one variable: 618 619 * filter_log_verbosity 620 621If you want to change the default behaviour, you can edit this 622line. Make sure Claws Mail is not running while you do 623this. 624 625It will be possible to access these setting via the GUI, as soon 626as I find the time to write a corresponding GTK plugin, or 627somebody else is interested in contributing that. 628 629=head1 EXAMPLE 630 631This section lists a small example of a Perl script file. I'm 632sure you get the idea.. 633 634 #-8<---------------------------------------------------- 635 # -*- perl -*- 636 637 # local functions 638 639 # Learn ham messages, and move them to specified folder. This is 640 # useful for making sure a bayes filter sees ham as well. 641 sub learn_and_move { 642 execute('put command to learn ham here'); 643 move(@_); 644 } 645 646 # Two-stage spam filter. Every email that scores higher than 15 647 # on SpamAssassin gets moved into the default trash folder. 648 # All mails lower than that, but higher than SpamAssassin's 649 # 'required_hits' go into #mh/mail/Spam. 650 sub spamcheck { 651 my $surely_spam = 15; 652 my $filepath = filepath; 653 my $spamc = `spamc -c < $filepath`; 654 my ($value,$threshold) = ($spamc =~ m|([-.,0-9]+)/([-.,0-9]+)|); 655 if($value >= $surely_spam) { 656 mark_as_read; 657 move_to_trash; 658 } 659 if($value >= $threshold) {mark_as_read; move '#mh/mail/Spam';} 660 } 661 662 # Perl script execution starts here. 663 664 # Some specific sorting 665 learn_and_move '#mh/mail/MailLists/Claws Mail/user' 666 if matchcase('sender','claws-mail-users-admin@lists.sourceforge.net'); 667 learn_and_move '#mh/mail/MailLists/Sylpheed' 668 if matchcase('list-id','sylpheed.good-day.net'); 669 670 # Implement incoming folders using addressbook 671 # attributes. Target folders for specific email addresses are 672 # stored directly in the addressbook. This way, if an email 673 # address changes, we only have to update the addressbook, not 674 # the filter rules! Besides that, we can greatly unclutter the 675 # filter script. 676 677 # get the email address in the from header 678 my $fromheader = header "from"; 679 my ($from) = extract_addresses $fromheader; 680 681 # check if this email address has an associated attribute 682 # called "incoming_folder". If if has, the value of this 683 # attribute is supposed to be the target folder. 684 my $value = get_attribute_value $from, "incoming_folder"; 685 learn_and_move($value) if $value; 686 687 # An example of a whitelist: If the from-address is in my 688 # "office" addressbook, move the mail to folder #mh/mail/office 689 learn_and_move '#mh/mail/office' if from_in_addressbook("office"); 690 691 # If the from-address is in any other addressbook, move the 692 # mail to folder #mh/mail/inbox/known 693 learn_and_move '#mh/mail/inbox/known' if from_in_addressbook; 694 695 # Feed the remaining mails through SpamAssassin. 696 spamcheck; 697 698 # mails that make it to the end of the script are passed on to 699 # the internal filtering engine. If the internal rules don't say 700 # otherwise, the mails end up in the default inbox. 701 #-8<---------------------------------------------------- 702 703 704=head1 BUGS 705 706=over 4 707 708=item * 709 710Do B<not> use this plugin together with other filtering plugins, 711especially the B<Spamassassin> and B<ClamAV> plugins. They are 712registered on the same hook and the order in which the plugins 713are executed is not guaranteed. 714 715=item * 716 717The filter script is not (yet) updated automatically when a 718folder gets renamed. The same applies for folder names in 719addressbook user attributes. 720 721=item * 722 723This plugin has only be tested with POP3 accounts. If you have 724experiences with IMAP or newsgroup accounts, drop me a message. 725 726=item * 727 728Warning during compile time: 729 730 *** Warning: Linking the shared library perl_plugin.la against the 731 *** static library 732 /usr/lib/perl5/5.8.3/i586-linux-thread-multi/auto/DynaLoader/DynaLoader.a 733 is not portable! 734 735Ideas to solve this one are welcome :-) 736 737=back 738 739Please report comments, suggestions and bugreports to the address 740given in the L</AUTHOR> section of this document. 741 742 743=head1 LICENSE and (no) WARRANTY 744 745This program is free software; you can redistribute it and/or 746modify it under the terms of the GNU General Public 747License as published by the Free Software Foundation; 748either version 3 of the License, or (at your option) any later 749version. 750 751This program is distributed in the hope that it will be useful, 752but WITHOUT ANY WARRANTY; without even the implied warranty of 753MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 754GNU General Public License for more details. 755 756You should have received a copy of the GNU General Public License 757along with this program. If not, see http://www.gnu.org/licenses/. 758 759=head1 SEE ALSO 760 761claws-mail(1), perl(1) 762 763 764=head1 AUTHOR 765 766Holger Berndt <berndth@gmx.de> 767 768=cut 769