File Coverage

blib/lib/Mail/Bulkmail/DummyServer.pm
Criterion Covered Total %
statement 51 52 98.0
branch 11 20 55.0
condition 2 5 40.0
subroutine 10 11 90.9
pod 2 2 100.0
total 76 90 84.4


line stmt bran cond sub pod time code
1             package Mail::Bulkmail::DummyServer;
2              
3             # Copyright and (c) 2003 James A Thomason III (jim@jimandkoka.com). All rights reserved.
4             # Mail::Bulkmail::DummyServer is distributed under the terms of the Perl Artistic License.
5              
6             =pod
7              
8             =head1 NAME
9              
10             Mail::Bulkmail::DummyServer - dummy class for dummy server objects
11              
12             =head1 AUTHOR
13              
14             Jim Thomason, jim@jimandkoka.com
15              
16             =head1 DESCRIPTION
17              
18             Mail::Bulkmail::DummyServer is a drop in replacement for Mail::Bulkmail::Server.
19              
20             Sometimes you just want to test things on your end - make sure your list iterates properly, make
21             sure your mail merge is functioning fine, make sure your logging functions are correct, whatever.
22             And in those cases, you probably don't want to worry about futzing around with your SMTP relay and
23             sending junk messages through it that you don't care about. Not to mention the fact that those
24             probably will need to be inspected and deleted later. A hassle for debugging.
25              
26             Enter DummyServer. This is a subclass of Mail::Bulkmail::Server that behaves exactly the same
27             except for the fact that it doesn't actually connect to a server. Instead, it sends all data
28             that would be going to the server to a file instead. This file should be specified in the conf file.
29              
30             #in your conf file
31             define package Mail::Bulkmail::DummyServer
32             dummy_file = ./my.dummy.file
33              
34             Now, instead of sending commands to your SMTP relay, they'll get sent to ./my.dummy.file for easy
35             inspection at a later date.
36              
37             =cut
38              
39 1     1   7005 use Mail::Bulkmail::Server;
  1         4  
  1         16  
40             @ISA = qw(Mail::Bulkmail::Server);
41              
42             $VERSION = '3.12';
43              
44 1     1   8 use strict;
  1         2  
  1         49  
45 1     1   8 use warnings;
  1         3  
  1         4414  
46              
47             =pod
48              
49             =head1 CLASS ATTRIBUTES
50              
51             =over 11
52              
53             =item dummy_file
54              
55             Stores the dummy_file that you want to output your data to.
56              
57             =back
58              
59             =cut
60              
61             __PACKAGE__->add_attr('dummy_file');
62              
63             # this is used for tied filehandles to internally hold the dummy socket
64             __PACKAGE__->add_attr('_socket');
65              
66             =pod
67              
68             =head1 METHODS
69              
70             =over 11
71              
72             =item connect
73              
74             "connects" to your DummyServer. Actually, internally it ties a filehandle onto this package.
75             Yes, this thing has a (minimal) implementation of a tied handle class to accomplish this feat.
76              
77             This method is known to return
78              
79             MBDu001 - server won't say EHLO
80              
81             =cut
82              
83             sub connect {
84 1     1 1 2 my $self = shift;
85              
86 1         7 local $\ = "\015\012";
87 1         7 local $/ = "\015\012";
88              
89 1         16 my $h = $self->gen_handle();
90 1         12 tie *$h, "Mail::Bulkmail::DummyServer", $self;
91              
92 1         16 $self->socket($h);
93              
94             #We're either given a domain, or we'll build it based on who the message is from
95 1         6 my $domain = $self->Domain;
96              
97 1         9 print $h "EHLO $domain";
98              
99 1   50     6 my $response = <$h> || "";
100 1 50 33     16 return $self->error("Server won't say EHLO: $response", "MBDu001") if ! $response || $response =~ /^[45]/;
101              
102 1         6 $self->connected(1);
103 1         7 return $self;
104             };
105              
106             # TIEHANDLE, as usual, ties a filehandle onto this class. It reads the file that is defined
107             # _in_the_conf_file at Mail::Bulkmail::DummyServer->dummy_file, tries to open it (dies with an
108             # error if it can't), and then ties our filehandle to the just opened file.
109             sub TIEHANDLE {
110              
111 1     1   7 my $class = shift;
112 1         3 my $self = shift;
113              
114 1         5 my $file = $self->dummy_file();
115              
116 1         10 my $handle = Mail::Bulkmail::Object->gen_handle();
117              
118 1 50       101 open ($handle, ">>$file") || die $!;
119              
120 1         13 return $class->new('_socket' => $handle);
121             };
122              
123             # in case our filehandle is fetched, just display some minimal information, namely the fact
124             # that we're in DummyServer, and the name of the dummy file
125             sub FETCH {
126 0     0   0 return "DummyServer at file : " . shift->_socket;
127             };
128              
129             # prints to our dummy file. Uses sendmail crlfs, and tacks on a note that we're starting
130             # a new message if we get a RSET command
131             sub PRINT {
132              
133 13     13   47 my $f = shift->_socket;
134              
135 13         64 local $\ = "\015\012";
136 13         37 local $/ = "\015\012";
137              
138 13 100       43 if ($_[0] eq 'RSET'){
139 3 50       14 print $f "--------NEW MESSAGE (connection reset)-------" if $f;
140             };
141              
142 13 50       50 print $f @_ if $f;
143              
144 13         76 return 1;
145             };
146              
147             sub FILENO {
148 12     12   35 my $f = shift->_socket;
149 12         82 my $n = fileno($f);
150             };
151              
152             # We can't read from this file, it's output only. However, we need to return something since
153             # talk_and_respond is expecting to read information from its SMTP socket
154              
155             sub READLINE {
156 13     13   761 return "250 bullshit all happy-happy" . scalar localtime() . "\015\012";
157             };
158              
159             # closes our filehandle
160              
161             sub CLOSE {
162 1     1   5 my $f = shift->_socket;
163 1 50       9034 close $f if $f;
164 1         20 return 1;
165             };
166              
167             =pod
168              
169             =item disconnect
170              
171             overloaded disconnect method. Wipes out the internal socket as usual, but doesn't try
172             to say RSET or QUIT to the server.
173              
174             disconnect can also disconnect quietly, i.e., it won't try to issue a RSET and then quit before closing the socket.
175              
176             $server->disconnect(); #issues RSET and quit
177             $server->disconnect('quietly'); #issues nothing
178              
179             =back
180              
181             =cut
182              
183             sub disconnect {
184 1     1 1 2 my $self = shift;
185 1         3 my $quietly = shift;
186              
187 1 50       5 return $self unless $self->connected();
188              
189 1 50       8 $self->talk_and_respond('RSET') unless $quietly; #just to be polite
190 1 50       12 $self->talk_and_respond('quit') unless $quietly;
191              
192 1 50       6 if (my $socket = $self->socket) {
193 1         23 close $socket;
194 1         8 $socket = undef;
195             };
196 1         21 $self->socket(undef);
197 1         7 $self->connected(0);
198 1         5 return $self;
199             };
200              
201             1;
202              
203             __END__