3 =head1 NAME $RCSfile: Mail.pm,v $
5 A simplified approach to sending email
13 Andrew DeFaria <Andrew@ClearSCM.com>
21 Thu Jan 5 15:15:29 PST 2006
25 $Date: 2012/09/25 01:34:10 $
31 Conveniently send email.
33 my $msg = "<h1>The Daily News</h1><p>Today in the news...</p>";
36 to => "somebody\@somewhere.com",
37 cc => "sombody_else\@somewhere.com",
38 subject => "Today's News",
43 open STATUS_REPORT, "status.html";
46 to => "boss\@mycompany.com",
47 bcc => "mysecret\@mailbox.com",
48 subject => "Weekly Status Report",
49 data => STATUS_REPORT,
50 footing => "Another day - Another dollar!"
57 Sending email from Perl scripts is another one of those things that is
58 often reinvented over and over. Well... This is yet another
59 reinvention I guess. The goal here is to allow for a simplifed
60 approach to sending email while still allowing MIME or rich text email
63 Additionally a multipart (plain text and HTML'ized) email will be send
64 if mode is set to html. Finally, if attempting to send HTML mail, if
65 we cannot find the appropriate dependent modules we'll fall back to
70 The following routines are exported:
94 my $mail_conf = dirname(__FILE__) . '/../etc/mail.conf';
97 %config = GetConfig $mail_conf;
99 $config{SMTPHOST} = $ENV{SMTPHOST} || $config{SMTPHOST};
101 $err = "SMTPHOST not defined in $mail_conf nor in the environment variable SMTPHOST"
102 unless $config{SMTPHOST};
105 $config{SMTPFROM} = $ENV{SMTPFROM} || $config{SMTPFROM};
107 $err = "SMTPFROM not defined in $mail_conf nor in the environment variable SMTPFROM"
108 unless $config{SMTPFROM};
111 $err = "Unable to read mail config file $mail_conf";
115 my $length = int(rand 16);
117 my @charset = ('A'..'Z', 'a'..'z', 0..9);
120 $randStr .= $charset[rand @charset] for 0..$length;
130 =head2 mail (<parms>)
132 Send email. The following OO style arguments are supported:
144 The from email address. If not specified then defaults to $ENV{SMTPFROM}.
148 Comma separated list of email addresses to set the mail to. At least
149 one address must be specified.
153 Comma separated list of email addresses to cc the mail to.
157 Comma separated list of email addresses to bcc the mail to.
161 Subject line for email (Default: "(no subject)")
165 Mode to send the email as. Values can be "plain", "text/plain",
170 Generate a random From email address.
174 Either a scalar that contains the message or a filehandle to an open
175 file which contains the message. Can contain HTML if mode = HTML.
179 Text to be included at the beginning of the email message. Can
180 contain HTML if mode = HTML.
184 Text to be included at the end fo the email message. Can contain HTML
217 # If from isn't specified we'll use a default
218 my $from = $parms{from} || $config{SMTPFROM};
220 if ($parms{randomizeFrom}) {
221 # Generate a random From address
222 my $username = randStr;
223 my $domain = randStr;
225 $from = "$username\@defaria.com";
228 my $me = "Mail::mail";
230 # Make arrays for to, cc and bcc
231 my @to = split /, */, $parms{to};
232 my @cc = split /, */, $parms{cc} if $parms{cc};
233 my @bcc = split /, */, $parms{bcc} if $parms{bcc};
235 error "$me: You must specify \"to\"" if @to == 0;
236 warning "$me: You should specify \"subject\"" unless $parms{subject};
238 my $subject = $parms{subject} || "(no subject)";
243 $mode = "text/plain";
244 } elsif ($parms{mode} eq "plain" or $parms{mode} eq "text/plain") {
245 $mode = "text/plain";
246 } elsif ($parms{mode} eq "html") {
248 } elsif ($parms{mode} eq "html") {
250 # Make sure we can get our modules...
251 eval { require MIME::Entity }
252 or error "Unable to find MIME::Entity module", 1;
253 eval { require HTML::Parser }
254 or error "Unable to find HTML::Parser module", 1;
255 eval { require HTML::FormatText }
256 or error "Unable to find HTML::FormatText module", 1;
257 eval { require HTML::TreeBuilder }
258 or error "Unable to find HTML::TreeBuilder module", 1;
260 error "Mode, ${parms{mode}}, is invalid - should be plain or html", 1;
264 my $smtp = Net::SMTP->new($config{SMTPHOST})
265 or error "Unable to connect to mail server: $config{SMTPHOST}", 1;
270 # Who are we sending to...
271 $smtp->to ($_, {SkipBad => 1}) for (@to);
272 $smtp->cc ($_, {SkipBad => 1}) for (@cc);
273 $smtp->bcc ($_, {SkipBad => 1}) for (@bcc);
275 # Now write the headers
277 $smtp->datasend("From: $from\n");
278 $smtp->datasend("To: $_\n") for (@to);
279 $smtp->datasend("Cc: $_\n") for (@cc);
280 $smtp->datasend("Subject: $subject\n");
281 $smtp->datasend("Content-Type: $mode\n");
282 $smtp->datasend("\n");
284 # If heading is specified then the user wants this stuff before the main
286 my $msgdata = $parms{heading};
287 chomp $msgdata if $msgdata;
289 # If $parms{data} is a GLOB we'll assume it's a FILE reference.
290 if (ref ($parms{data}) eq "GLOB") {
292 my $datafile = $parms{data};
294 # Just because it's a file reference doesn't mean that it's a valid file
296 unless (eval { @lines = <$datafile> }) {
297 error "$me: File passed in to mail is invalid - $!", 1
300 $msgdata .= join "", @lines;
302 $msgdata .= $parms{data};
305 # If footing is specified then the user wants this stuff after the main
307 $msgdata .= $parms{footing} if defined $parms{footing};
309 # if the user requested html mode then convert the message to HTML
310 if ($mode eq "multipart") {
311 # Create multipart container
312 my $container = MIME::Entity->build (
313 Type => "multipart/alternative",
318 # Create a textual version of the HTML
319 my $html = HTML::TreeBuilder->new;
320 $html->parse($msgdata);
322 my $formatter = HTML::FormatText->new(
326 my $plain_text = $formatter->format($html);
328 # Create ASCII attachment first
330 Type => "text/plain",
331 Encoding => "quoted-printable",
335 # Create HTML attachment
338 Encoding => "quoted-printable",
342 $container->smtpsend(Host => $smtp);
345 $smtp->datasend($msgdata);
359 =head2 CONFIGURATION AND ENVIRONMENT
361 SMTPHOST: Set to the appropriate mail server
363 SMTPFROM: Set to a from address to be used as a default
375 (Optionally - i.e. if html email is requested:)
377 =for html <p><a href="http://search.cpan.org/search?query=MIME::Entity">MIME::Entity</a>
379 =for html <p><a href="http://search.cpan.org/search?query=HTML::Parser">HTML::Parser</a>
381 =for html <p><a href="http://search.cpan.org/search?query=HTML::FormatText">HTML::FormatText</a>
383 =for html <p><a href="http://search.cpan.org/search?query=HTML::TreeBuilder">HTML::TreeBuilder</a>
385 =head3 ClearSCM Perl Modules
387 =for html <p><a href="/php/scm_man.php?file=lib/Display.pm">Display</a></p>
389 =for html <p><a href="/php/scm_man.php?file=lib/GetConfig.pm">GetConfig</a></p>
391 =head2 INCOMPATABILITIES
395 =head2 BUGS AND LIMITATIONS
397 There are no known bugs in this module.
399 Please report problems to Andrew DeFaria >Andrew@ClearSCM.com>.
401 =head2 LICENSE AND COPYRIGHT
403 This Perl Module is freely available; you can redistribute it and/or
404 modify it under the terms of the GNU General Public License as
405 published by the Free Software Foundation; either version 2 of the
406 License, or (at your option) any later version.
408 This Perl Module is distributed in the hope that it will be useful,
409 but WITHOUT ANY WARRANTY; without even the implied warranty of
410 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
411 General Public License (L<http://www.gnu.org/copyleft/gpl.html>) for more
414 You should have received a copy of the GNU General Public License
415 along with this Perl Module; if not, write to the Free Software Foundation,
416 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.