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