File Coverage

blib/lib/Test/Mail.pm
Criterion Covered Total %
statement 17 39 43.5
branch 0 2 0.0
condition n/a
subroutine 5 8 62.5
pod 4 4 100.0
total 26 53 49.0


line stmt bran cond sub pod time code
1             package Test::Mail;
2              
3 2     2   45851 use warnings;
  2         6  
  2         65  
4 2     2   11 use strict;
  2         3  
  2         65  
5              
6 2     2   10 use Carp;
  2         9  
  2         160  
7 2     2   1870 use Mail::Header;
  2         10895  
  2         1006  
8              
9             require Exporter;
10              
11             =head1 NAME
12              
13             Test::Mail - Test framework for email applications
14              
15             =head1 VERSION
16              
17             Version 0.06
18              
19             =cut
20              
21             our $VERSION = '0.06';
22              
23             =head1 SYNOPSIS
24              
25              
26             use Test::Mail
27             my $tm = Test::Mail->new( logfile => $logfile );
28             $tm->accept();
29             sub first_test { }
30             sub second_test { }
31             ...
32              
33             =head1 DESCRIPTION
34              
35             Test::Mail provides a framework for testing applications which send and
36             receive email.
37              
38             A typical example of an email application might send a notification to a
39             certain email address, setting certain headers in certain ways and
40             having certain content in the body of the email. It would be nice to be
41             able to test these things automatically, however most email applications
42             are currently tested by visual inspection of the email received.
43              
44             Test::Mail allows you to automate the testing of email applications by
45             piping any relevant email through a Test::Mail script.
46              
47             "Relevant" email is identified by the presence of an X-Test-Mail:
48             header. You should set this email in your application or whatever you
49             use to generate the mail.
50              
51             X-Test-Mail: birthday_notification
52              
53             The value of that header is the name of a subroutine which
54             exists in your Test::Mail script. The subroutine contains Test::More
55             tests to run on the email:
56              
57             sub birthday_notification {
58             is($header->get("From:"), 'birthdays@example.com', "From address check");
59             like($body, qr/Today's Birthdays/, "Email body check");
60             }
61              
62             This allows you to have tests for multiple different kinds of email in
63             one script.
64              
65             Note that $header and $body are set by Test::Mail for your convenience.
66             $header is a Mail::Header object. $body is the body of the email as a
67             single string. MIME attachments etc are not supported (yet).
68              
69             The results of the tests run are output to the logfile you specify, and
70             look something like this:
71              
72             # test results for birthday_notification for
73             ok 1 - From address check
74             ok 2 - Email body check
75              
76             # test results for support_request for
77             ok 1 - To address check
78             not ok 2 - Subject line
79             not ok 3 - Included ticket number
80             ok 4 - Body contains plain text
81              
82             Note that while these are roughly similar to normal CPAN test output
83             conventions, counting only occurs on a per-email basis
84              
85             =head2 Sending incoming mail to Test::Mail
86              
87             To call Test::Mail, simply put a suitable filter in your .procmailrc,
88             Mail::Audit script, or whatever you use to filter your email. Here's
89             how I'd do it with Mail::Audit:
90              
91             if ($mail->{obj}->head->get("X-Test-Mail")) {
92             $mail->pipe("testmail.pl");
93             }
94              
95             If for some reason you want to test mail that doesn't already have an
96             X-Test-Mail: header, you could do something like:
97              
98             if ($mail->{subject} =~ /test/i) {
99             $mail->{obj}->head->add("X-Test-Mail", "subject_auto");
100             $mail->pipe("testmail.pl");
101             }
102              
103             =head2 Unaddressed issues
104              
105             The above is a rough outline of version 1. There are several issues I
106             don't yet know how to deal with, which I'm listing here just in case
107             anyone has any good ideas:
108              
109             =over 4
110              
111             =item *
112              
113             Sending output somewhere more useful than a logfile
114              
115             =item *
116              
117             Integrating into a real "test suite" that's friendly to Test::Harness
118              
119             =item *
120              
121             Handling MIME in a suitable way
122              
123             =back
124              
125             =head1 METHODS
126              
127             =head2 new()
128              
129             Constructor method. Takes a hash of arguments. The only current argument is
130             "logfile" which is the file to which test logs will be sent.
131              
132             =cut
133              
134             sub new {
135 1     1 1 454 shift;
136 1         4 my (%args) = @_;
137 1         2 my $self = \%args;
138              
139 1         2 bless $self;
140 1         2 return $self;
141             }
142              
143             =head2 accept()
144              
145             Accept a single email and test it. Doesn't take any args.
146              
147             This will run the email through whatever subroutine is described in the
148             "X-Test-Mail" header.
149              
150             =cut
151              
152             sub accept {
153 0     0 1   my ($self) = @_;
154              
155 0           $self->{header} = new Mail::Header \*STDIN, Modify => 0, MailFrom => 'IGNORE';
156 0           $self->{header}->unfold(); # Recombine multi-line headers
157              
158             {
159             # Slurp in the message body in one fell swoop
160 0           local $/;
  0            
161 0           undef $/;
162 0           $self->{body} = ;
163             }
164              
165 0           my $sub = $self->{header}->get("X-Test-Mail:");
166 0           my $msgid = $self->{header}->get("Message-ID:");
167 0           chomp ($sub, $msgid);
168              
169 0 0         open LOG, ">>$self->{logfile}"
170             or croak "Can't open $self->{logfile}: $!";
171              
172 0           print LOG "\n# Test results for $sub for $msgid\n";
173 0           print LOG "# ", scalar localtime, "\n";
174              
175 0           my ($package) = caller;
176              
177 0           *Test::Simple::TESTOUT = \*LOG;
178 0           *Test::Simple::TESTERR = \*LOG;
179 0           *Test::More::TESTERR = \*LOG;
180 0           eval qq(
181             package $package;
182             use Test::More 'no_plan';
183             &${package}::$sub;
184             );
185             }
186              
187             =head2 header()
188              
189             Convenience accessor method for the header of the email. Returns a Mail::Header
190             object.
191              
192             =cut
193              
194             sub header {
195 0     0 1   my ($self) = @_;
196 0           return $self->{header};
197             }
198              
199             =head2 body()
200              
201             Convenience accessor method for the body of the email. Returns a plain text
202             string.
203              
204             =cut
205              
206             sub body {
207 0     0 1   my ($self) = @_;
208 0           return $self->{body};
209             }
210              
211             return 1;
212              
213             =head1 AUTHOR
214              
215             Kirrily Robert, C<< >>
216              
217             =head1 BUGS
218              
219             Please report any bugs or feature requests to
220             C, or through the web interface at
221             L.
222             I will be notified, and then you'll automatically be notified of progress on
223             your bug as I make changes.
224              
225             =head1 SUPPORT
226              
227             You can find documentation for this module with the perldoc command.
228              
229             perldoc Test::Mail
230              
231             You can also look for information at:
232              
233             =over 4
234              
235             =item * AnnoCPAN: Annotated CPAN documentation
236              
237             L
238              
239             =item * CPAN Ratings
240              
241             L
242              
243             =item * RT: CPAN's request tracker
244              
245             L
246              
247             =item * Search CPAN
248              
249             L
250              
251             =back
252              
253             =head1 ACKNOWLEDGEMENTS
254              
255             =head1 COPYRIGHT & LICENSE
256              
257             Copyright 2007 Kirrily Robert, all rights reserved.
258              
259             This program is free software; you can redistribute it and/or modify it
260             under the same terms as Perl itself.
261              
262             =cut
263              
264             1; # End of Test::Mail