File Coverage

blib/lib/Mail/RoundTrip.pm
Criterion Covered Total %
statement 33 63 52.3
branch 0 6 0.0
condition 0 6 0.0
subroutine 11 15 73.3
pod 2 2 100.0
total 46 92 50.0


line stmt bran cond sub pod time code
1             package Mail::RoundTrip;
2              
3 2     2   68852 use 5.006;
  2         9  
  2         72  
4 2     2   11 use strict;
  2         4  
  2         73  
5 2     2   14 use warnings;
  2         21  
  2         68  
6 2     2   28171 use Moo;
  2         91513  
  2         17  
7 2     2   8368 use JSON;
  2         69838  
  2         13  
8 2     2   2298 use UUID::Tiny qw(:std);
  2         81546  
  2         620  
9 2     2   1880 use Email::Sender::Simple qw(sendmail);
  2         632100  
  2         20  
10 2     2   667 use Email::Simple;
  2         4  
  2         52  
11 2     2   11 use Email::Simple::Creator;
  2         14  
  2         42  
12 2     2   2849 use File::Slurp;
  2         25967  
  2         944  
13 2     2   30 use Carp;
  2         4  
  2         1982  
14              
15             =head1 NAME
16              
17             Mail::RoundTrip - Management routines for round trip validation of users' emails
18              
19             =head1 VERSION
20              
21             Version 0.02
22              
23             =cut
24              
25             our $VERSION = '0.02';
26              
27              
28             =head1 SYNOPSIS
29              
30             To send validation email:
31              
32             my $validator = Mail::RoundTrip->new(
33             spool_dir => '/var/spool/myapp/contacts',
34             address => 'test@example.org',
35             data => $data,
36             from => 'me@example.com',
37             reply_to => 'not_me@example.com',
38             );
39             my $code = $validator->code;
40             $validator->send_confirmation(template => $template);
41              
42             To retrieve based on validation code:
43              
44             my $data = Mail::RoundTrip->get_data( code => $code, spool_dir => $dir );
45              
46             =head1 DESCRIPTION
47              
48             Many web applicatins rely on some sort of round-trip validation of user emails.
49             This verifies that the email address, for example, is actually owned by the
50             user. This module provides a minimalist set of routines for managing this
51             process.
52              
53             The module is curently minimalistic because it is assumed it will provide the
54             common back-ends for a number of related verification routines. Extensions and
55             feature requests are welcome. The module exposes a fully object-oriented
56             interface.
57              
58             The module basically provides a minimalist spooling service for holding data for
59             later processing once the code has been provided.
60              
61             =head1 PROPERTIES
62              
63             =head2 address
64              
65             The email address to be confirmed.
66              
67             =head2 code
68              
69             This is the random code used to authenticate the request. Currently this is
70             generated as an sha2 256-bit hash of a pseudo-random value.
71              
72             =head2 from
73              
74             The address in the from header.
75              
76             =head2 reply_to
77              
78             The address in the reply to header.
79              
80             =head2 return_path
81              
82             The return path fo the email.
83              
84             =head2 data
85              
86             The data to be queued.
87              
88             =head2 spool_dir
89              
90             The spool directory to be used.
91              
92             =cut
93              
94             has address => (is =>'ro', required => 0);
95              
96             has code => (is => 'lazy');
97              
98             has data => (is => 'ro', required => 0);
99              
100             has from => (is => 'ro', required => 0);
101              
102             has reply_to => (is => 'ro', required => 0);
103              
104             has return_path => (is => 'ro', requird => 0);
105              
106             has spool_dir => (is => 'ro', required => 1);
107              
108             sub _build_code {
109 0     0     my ($self) = @_;
110 0           my $uuid = create_uuid_as_string();
111 0 0         return $uuid unless -f $self->spool_dir . '/' . $uuid;
112 0           return $self->to_build_code; # If file exists, try again
113             }
114              
115             =head1 METHODS
116              
117             =head2 send_confirmation(subject_prefix = $subpfx, template => $template)
118              
119             This process the text in template $template, replacing __CODE__ with
120             $self->code, setting the subject to "$subpfx $self->code" and sending out the
121             email to the address provided.
122              
123             =cut
124              
125             sub send_confirmation {
126 0     0 1   my $self = shift @_;
127 0           my %args = @_;
128 0           my $template = $args{template};
129 0 0         croak 'No template defined for email' unless $template;
130 0           my $code = $self->code;
131 0           $template =~ s/__CODE__/$code/g;
132 0   0       my $return_path = $self->return_path || $self->from;
133 0   0       my $reply_to = $self->reply_to || $self->from;
134 0           my $email = Email::Simple->create(
135             header => [
136             To => $self->address,
137             From => $self->from,
138             "Reply-To" => $reply_to,
139             'Return-path' => $return_path
140             ],
141             body => $template,
142             );
143 0           _spool($self);
144 0           return sendmail($email);
145             }
146              
147             sub _spool {
148 0     0     my ($self) = @_;
149 0           my $spooldir = $self->spool_dir;
150 0           $spooldir =~ s|/+$||; # Get rid of trailing slashes
151 0           my $filename = $self->code;
152 0           my $json = encode_json($self->data);
153 0           write_file("$spooldir/$filename", {no_clobber => 1}, $json);
154             }
155            
156              
157             =head2 get_data(code => $code, spool_dir => $directory)
158              
159             This gets the data from spool_dir/directory and unlinks the file.
160              
161             =cut
162              
163             sub get_data{
164 0     0 1   my ($self) = shift @_;
165 0           my %args = @_;
166 0           my $spooldir = $args{spool_dir};
167 0 0         croak 'No Spool Dir provided' unless defined $spooldir;
168 0           $spooldir =~ s|/+$||; # Get rid of trailing slashes
169 0           my $filename = $args{code};
170 0           my $json = read_file("$spooldir/$filename");
171 0           unlink("$spooldir/$filename");
172 0           return decode_json($json);
173             }
174              
175              
176             =head1 AUTHOR
177              
178             Chris Travers, C<< >>
179              
180             =head1 BUGS
181              
182             Please report any bugs or feature requests to C, or through
183             the web interface at L. I will be notified, and then you'll
184             automatically be notified of progress on your bug as I make changes.
185              
186              
187              
188              
189             =head1 SUPPORT
190              
191             You can find documentation for this module with the perldoc command.
192              
193             perldoc Mail::RoundTrip
194              
195              
196             You can also look for information at:
197              
198             =over 4
199              
200             =item * RT: CPAN's request tracker (report bugs here)
201              
202             L
203              
204             =item * AnnoCPAN: Annotated CPAN documentation
205              
206             L
207              
208             =item * CPAN Ratings
209              
210             L
211              
212             =item * Search CPAN
213              
214             L
215              
216             =back
217              
218              
219             =head1 ACKNOWLEDGEMENTS
220              
221              
222             =head1 LICENSE AND COPYRIGHT
223              
224             Copyright 2013 Chris Travers.
225              
226             This program is released under the following license: BSD
227              
228              
229             =cut
230              
231             1; # End of Mail::RoundTrip