Skip to content

Commit

Permalink
Foswikitask:Item456: ported to Foswiki Foswikitask:Item4955: config o…
Browse files Browse the repository at this point in the history
…ptions moved to 'Mail and Proxies' Foswikitask:Item5829: force new revision on each submission Foswikitask:Item5843: extract target topic from CC: field - general improvement to rules for extracting the target topic

git-svn-id: http://svn.foswiki.org/trunk/MailInContrib@2328 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
CrawfordCurrie authored and CrawfordCurrie committed Feb 3, 2009
1 parent 42be49a commit 142c85e
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 42 deletions.
30 changes: 21 additions & 9 deletions data/System/MailInContrib.txt
Expand Up @@ -40,10 +40,21 @@ Attachments to the mail get treated as attachments by Foswiki, and attached to t
Note that =mailincron= will only process messages that have arrived since the last time it ran. So if there was an error adding a mail, it won't attempt to add it again even if it is still in the inbox.

---+ Where the mail gets added
The target topic for a mail is normally specified in the =Subject:= of the mail. You just put Web.Topic as the first thing on the subject line, optionally followed by a colon and other subject text. Alternatively you can configure the module to examine the =To:= field in the mail and get the topic name from there instead.
* If a topic is specified, but doesn't exist, it will be created.
* If there is no web name specified, then you can configure a default web to accept those mails.
* If a non-existant web is specified, then it is an error.
By default the target topic for mail is specified in the =Subject:= of the mail. You just put Web.Topic as the first thing on the subject line, optionally followed by a colon and other subject text. If there is no web name specified, then you can configure a default web to accept those mails.
* A mail with a subject of =Schedule.MyClass= will be saved to Schedule.<nop>MyClass
* =Subject: Schedule.MyClass: timetable= will be saved to Schedule.<nop>MyClass
* =Subject: MyClass= will be saved to &lt;default web>.<nop>MyClass.
* =Subject: MyClass: timetable= will be saved to &lt;default web>.<nop>MyClass, if the default web is set as =Schedule=.
* If a topic specified on the =Subject:= line doesn't exist, it will be created.

You can also configure the module to examine the =To:= and =CC:= fields in the mail, and get the name of an existing topic from there instead.
* If a non-existant topic is specified, then it is an error.
* The first valid, existing topic found in the =To:= or =CC:= fields is taken, and overrides the =Subject:=.
* A mail addressed to =&lt;MyTopic@example.com>= will be saved in &lt;default web>.MyTopic
* A mail addressed to =&lt;Schedule.MyTopic@example.com>= will be saved in Schedule.<nop>MyTopic
* A mail addressed to ="Mylene Classe" &lt;Schedule.MyClass<nop>@example.com>= will be saved in Schedule.<nop>MyTopic
* A mail addressed to ="Mylene Classe" &lt;MyClass<nop>@example.com>= will be saved in &lt;default web>.<nop>MyTopic

You can also define a 'spambox' for each mail folder. A spambox is a topic that will take all messages that do _not_ have a valid topic.

The module can use special HTML comments in the topic to decide where to insert new emails within the text.
Expand Down Expand Up @@ -86,20 +97,21 @@ Make sure that the cron is run by a user with the permissions needed to read and

---++ Contrib Info

Another great Foswiki extension from the <a style="text-decoration:none" href="http://wikiring.com"><img src="%ATTACHURLPATH%/wikiringlogo20x20.png" alt="" /> *WikiRing* </a> - working together to improve your wiki experience!
Another great Foswiki extension from the <a style="text-decoration:none" href="http://wikiring.com"><img src="%ATTACHURLPATH%/wikiringlogo20x20.png" alt="" /> *WikiRing* </a> - *working together to improve your wiki experience!*

Many thanks to the following sponsors for supporting this work:
* [[http://www.evolvedmedianetwork.com][Evolved Media Network]]

| Author: | Foswiki:Main.CrawfordCurrie (http://c-dot.co.uk) |
| Copyright &copy;: | 2005, TWiki Contributors; 2008 Foswiki Contributors |
| Copyright &copy;: | 2005, TWiki Contributors<br />2008-2009 Foswiki Contributors |
| License: | GPL ([[http://www.gnu.org/copyleft/gpl.html][GNU General Public License]]) |
| Dependencies: | %$DEPENDENCIES% |
| Version: | %$VERSION% |
| Change History: | |
| 1 Aug 2008 | Bugs:Item5450: minor doc fix |
| 8 Sep 2007 | Bugs:Item4575 various ideas from Dev topic, tested against 4.2.0 |
| 12412 | Fixed Bugs:Item3334 by removing dependency on !FuncUsersContrib |
| 3 Feb 2009 | Foswikitask:Item456: ported to Foswiki Foswikitask:Item4955: config options moved to 'Mail and Proxies' Foswikitask:Item5829: force new revision on each submission Foswikitask:Item5843: extract target topic from CC: field - general improvement to rules for extracting the target topic |
| 1 Aug 2008 | TWikibug:Item5450: minor doc fix |
| 8 Sep 2007 | TWikibug:Item4575 various ideas from Dev topic, tested against 4.2.0 |
| 12412 | Fixed TWikibug:Item3334 by removing dependency on !FuncUsersContrib |
| 10239 | Added support for listing attachments in-line with the mail |
| 10182 | Fixed parser failures on multipart MIME messages |
| 10111 | Fixed problem with spaces in attachment names |
Expand Down
6 changes: 3 additions & 3 deletions data/System/MailInContribTemplate.txt
Expand Up @@ -3,9 +3,9 @@

*DO NOT MODIFY THIS TOPIC*

This is a normal TWiki topic, but it is also a template file, as described in %SYSTEMWEB%.SkinTemplates. It contains the template definitions used by the MailInContrib to insert mail messages in topics.
This is a normal topic, but it is also a template file, as described in %SYSTEMWEB%.SkinTemplates. It contains the template definitions used by the MailInContrib to insert mail messages in topics.

Each template is specified in the form of a pair of TWiki template definitions, (surrounded by verbatim tags below for readability). The template to use when inserting incoming mail in a topic is decided from the parameters in the =&lt;--MAIL--> comment in the topic. The default template is =normal=.
Each template is specified in the form of a pair of template definitions, (surrounded by verbatim tags below for readability). The template to use when inserting incoming mail in a topic is decided from the parameters in the =&lt;--MAIL--> comment in the topic. The default template is =normal=.

<verbatim>
%TMPL:DEF{MAILIN:normal}% * *%SUBJECT%*: %TEXT% -- %WIKIUSERNAME% - %SERVERTIME%%ATTACHMENTS%
Expand All @@ -20,7 +20,7 @@ Each template is specified in the form of a pair of TWiki template definitions,

*DO NOT MODIFY THIS TOPIC*

If you want to modify or add any templates, create the TWiki topic %SYSTEMWEB%.MailInContribUserTemplate. This topic is automatically included here if it exists, but it is *not* shipped with the MailInContrib. Any templates you define in %SYSTEMWEB%.MailInContribUserTemplate will override those defined here.
If you want to modify or add any templates, create the topic %SYSTEMWEB%.MailInContribUserTemplate. This topic is automatically included here if it exists, but it is *not* shipped with the MailInContrib. You can create this topic in individual webs, as described in %SYSTEMWEB%.SkinTemplates. In this case the template will only apply in that specific web.

<!-- The following line includes a *template* called "MailInUserContrib", which the template search rules automatically resolve to a *topic* called MailInContribUserTemplate. -->
%TMPL:INCLUDE{"MailInContribUser"}%
66 changes: 47 additions & 19 deletions lib/Foswiki/Contrib/MailInContrib.pm
@@ -1,11 +1,13 @@
#
# Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# Copyright (C) 2005 TWiki Contributors. All Rights Reserved.
# Copyright (C) 2008 Foswiki Contributors. All Rights Reserved.
# Copyright (C) 2009 Foswiki Contributors. All Rights Reserved.
# Foswiki Contributors are listed in the AUTHORS file in the root
# of this distribution.
# NOTE: Please extend that file, not this notice.
# of this distribution. NOTE: Please extend that file, not this notice.
#
# Additional copyrights apply to some or all of the code in this module
# as follows:
# Copyright (C) 2005 TWiki Contributors. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
Expand All @@ -22,6 +24,7 @@ package Foswiki::Contrib::MailInContrib;

use strict;
use Foswiki;
use Assert;

use Email::Folder;
use Email::FolderType::Net;
Expand Down Expand Up @@ -163,17 +166,18 @@ sub processInbox {
$received = $receipt if $receipt > $received;
}
}
unless ($received) {
if (!$received && $mail->header('Date')) {
# Use the send date
$received = Time::ParseDate::parsedate($mail->header('Date'));
}
$received ||= time();

# Try to get the target topic by
# 1. examining the "To" address to see if it is a valid web.wikiname (if
# enabled in config)
# 2. if the subject line starts with a valid Foswiki Web.WikiName (if optionally
# followed by a colon, the rest of the subject line will be ignored)
# 1. examining the "To" and "cc" addresses to see if either has
# a valid web.wikiname (if enabled in config)
# 2. if the subject line starts with a valid Foswiki Web.WikiName
# (if optionally followed by a colon, the rest of the subject
# line will be ignored)
# 3. Routing the comment to the spambox if it is enabled
# 4. Otherwise replying to the user to say "no thanks" if replyonnotopic
my( $web, $topic, $user );
Expand All @@ -190,8 +194,15 @@ sub processInbox {
if( $targets && scalar(@$targets)) {
$user = $targets->[0];
}
my $to = $mail->header('To');
$to =~ s/^.*<(.*)>.*$/$1/;

my @to = split(/,\s*/, $mail->header('To') || '');
if (defined $mail->header('CC')) {
push(@to, split(/,\s*/, $mail->header('CC')));
}
# Use the address in the <> if there is one
@to = map { /^.*<(.*)>.*$/ ? $1 : $_; } @to;
print STDERR "Targets: ", join(' ', @to),"\n" if $this->{debug};
print STDERR "Subject: $subject\n" if $this->{debug};

unless( $user ) {
unless( $box->{user} && ($user = _getUser( $box->{user} ))) {
Expand All @@ -203,16 +214,32 @@ sub processInbox {
}
}

print STDERR "User ",($user||'undefined'),"\n" if( $this->{debug} );

if( $box->{topicPath} =~ /\bto\b/ &&
$to =~ /^(?:($Foswiki::regex{webNameRegex})\.)($Foswiki::regex{wikiWordRegex})@/i) {
( $web, $topic ) = ( $1, $2 );
print STDERR "User is '",($user||'undefined'),"'\n"
if( $this->{debug} );

# See if we can get a valid web.topic out of to: or cc:
if( $box->{topicPath} =~ /\bto\b/) {
foreach my $target (@to) {
next unless $target =~ /^(?:($Foswiki::regex{webNameRegex})\.)($Foswiki::regex{topicNameRegex})\@/i;
my ($guessweb, $guesstopic) =
Foswiki::Func::normalizeWebTopicName(
($1 || $box->{defaultWeb}), $2);
if (Foswiki::Func::topicExists($guessweb, $guesstopic)) {
# Found an existing topic
($web, $topic) = ($guessweb, $guesstopic);
last;
}
}
}

# If we didn't get the name of an existing topic from the
# To: or CC:, use the Subject:
if( !$topic && $box->{topicPath} =~ /\bsubject\b/ &&
$subject =~
s/^\s*(?:($Foswiki::regex{webNameRegex})\.)?($Foswiki::regex{wikiWordRegex})(:\s*|\s*$)// ) {
( $web, $topic ) = ( $1, $2 );
/^\s*(?:($Foswiki::regex{webNameRegex})\.)?($Foswiki::regex{topicNameRegex})(:\s*|\s*$)/ ) {
($web, $topic) = Foswiki::Func::normalizeWebTopicName(
($1 || $box->{defaultWeb}), $2);
# This time the topic doesn't have to exist
}

$web ||= $box->{defaultWeb};
Expand Down Expand Up @@ -401,8 +428,9 @@ sub _saveTopic {

print STDERR "Save topic $web.$topic:\n$text\n" if( $this->{debug} );

ASSERT(!$meta || $meta->isa('Foswiki::Meta')) if DEBUG;
Foswiki::Func::saveTopic(
$web, $topic, $text, $meta,
$web, $topic, $meta, $text,
{ comment => "Submitted by e-mail",
forcenewrevision => 1} );

Expand Down
2 changes: 1 addition & 1 deletion lib/Foswiki/Contrib/MailInContrib/Config.spec
Expand Up @@ -63,7 +63,7 @@
# specify a full web.topicname
# </li>
# </ul>
$TWiki::cfg{MailInContrib} = [
$Foswiki::cfg{MailInContrib} = [
{
folder => 'pop://example_user:password@example.com/Inbox',
onError => 'log',
Expand Down
38 changes: 28 additions & 10 deletions test/unit/MailInContrib/MailInContribSuite.pm
Expand Up @@ -155,8 +155,18 @@ HERE

my( $m, $t ) = Foswiki::Func::readTopic($this->{test_web},$this->{test_topic});

$this->assert($t =~ s/^ *\* \*$this->{test_web}\.NotHere\*: Message 1 text here\s*-- $this->{users_web}\.MoleInnaHole -\s+\d+\s+\w+\s+\d+\s+-\s+\d+:\d+\n//m, $t);
$this->assert($t =~ s/^ *\* \*$this->{test_web}\.IgnoreThis\*: Message 2 text here\s*-- $this->{users_web}\.AllyGator -\s+\d+\s+\w+\s+\d+\s+-\s+\d+:\d+\n//m, $t);
$this->assert(0, $t) unless
$t =~ s/^\s*\*\s+\*$this->{test_web}\.NotHere\*:\s*//s;
$this->assert(0, $t) unless
$t =~ s/^Message 1 text here\s*//s;
$this->assert(0, $t) unless
$t =~ s/^_$this->{users_web}\.MoleInnaHole\s*\@\s*\d+\s+\w+\s+\d+\s+-\s+\d+:\d+_\s*//s;
$this->assert(0, $t) unless
$t =~ s/^ *\* \*$this->{test_web}\.IgnoreThis\*: //s;
$this->assert(0, $t) unless
$t =~ s/^Message 2 text here\s*//s;
$this->assert(0, $t) unless
$t =~ s/^_$this->{users_web}\.AllyGator\s*\@\s*\d+\s+\w+\s+\d+\s+-\s+\d+:\d+_//s;

$this->assert_matches(qr/^\s*$/, $t);
$this->assert_equals(0, scalar(@mails));
Expand Down Expand Up @@ -187,13 +197,22 @@ HERE
$this->sendTestMail($mail);
$box->{topicPath} = 'subject';
my $c = $this->cron();
$this->assert_null($c->{error});

my( $m, $t ) = Foswiki::Func::readTopic($this->{test_web},$this->{test_topic});

$this->assert($t =~ s/^\s*\* \*\*: Message 1 text here\s* -- $this->{users_web}\.MoleInnaHole -\s+\d+\s+\w+\s+\d+\s+-\s+\d+:\d+$//m, $t);
$this->assert($t =~ s/^ *\* \*SPAM\*: Message 2 text here\s*-- $this->{users_web}\.AllyGator -\s+\d+\s+\w+\s+\d+\s+-\s+\d+:\d+$//m);
if ($c->{error}) {
print STDERR $c->{error},"\n";
$this->assert_null($c->{error});
}

my( $m, $t ) = Foswiki::Func::readTopic(
$this->{test_web}, $this->{test_topic});

$this->assert(0, $t) unless
$t =~ s/^\s*\* \*$this->{test_web}.$this->{test_topic}\*: Message 1 text here\s*//s;
$this->assert(0, $t) unless
$t =~ s/^_$this->{users_web}\.MoleInnaHole\s*\@\s*\d+\s+\w+\s+\d+\s+-\s+\d+:\d+_//s;
$this->assert(0, $t) unless
$t =~ s/^\s*\*\s*\*$this->{test_web}.$this->{test_topic}: SPAM\*: Message 2 text here\s*//s;
$this->assert(0, $t) unless
$t =~ s/^_$this->{users_web}\.AllyGator\s*\@\s*\d+\s+\w+\s+\d+\s+-\s+\d+:\d+_//s;
$this->assert_matches(qr/^\s*$/, $t);
$this->assert_equals(0, scalar(@mails));
}
Expand Down Expand Up @@ -296,7 +315,7 @@ Date: Mon, 27 Feb 2006 00:33:58 -0800
From: "Ally Gator" <ally@masai.mara>
To: "Dick Head" <dhead@twiki.com>
Subject: $this->{test_web}.AnotherTopic: attachment test
Cc: another.idiot@twiki.com>
Cc: another.idiot@twiki.com
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_21658_5579231.1141029238540"
Expand Down Expand Up @@ -366,7 +385,6 @@ HERE
$box->{onSuccess} = 'reply';
my $c = $this->cron();

print STDERR "VBLO\n";
$this->assert_equals(1, scalar(@mails));
$this->assert_matches(qr/Thank you for your successful/, $mails[0]);

Expand Down

0 comments on commit 142c85e

Please sign in to comment.