File Coverage

blib/lib/LWP/Protocol/mailto.pm
Criterion Covered Total %
statement 16 83 19.2
branch 4 54 7.4
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 25 142 17.6


line stmt bran cond sub pod time code
1             package LWP::Protocol::mailto;
2             $LWP::Protocol::mailto::VERSION = '6.29';
3             # This module implements the mailto protocol. It is just a simple
4             # frontend to the Unix sendmail program except on MacOS, where it uses
5             # Mail::Internet.
6              
7             require HTTP::Request;
8             require HTTP::Response;
9             require HTTP::Status;
10              
11 1     1   9 use Carp;
  1         3  
  1         100  
12 1     1   8 use strict;
  1         2  
  1         36  
13              
14 1     1   6 use base qw(LWP::Protocol);
  1         3  
  1         1566  
15             our $SENDMAIL;
16              
17             unless ($SENDMAIL = $ENV{SENDMAIL}) {
18             for my $sm (qw(/usr/sbin/sendmail
19             /usr/lib/sendmail
20             /usr/ucblib/sendmail
21             ))
22             {
23             if (-x $sm) {
24             $SENDMAIL = $sm;
25             last;
26             }
27             }
28             die "Can't find the 'sendmail' program" unless $SENDMAIL;
29             }
30              
31             sub request
32             {
33 1     1 1 4 my($self, $request, $proxy, $arg, $size) = @_;
34              
35 1 50       7 my ($mail, $addr) if $^O eq "MacOS";
36 1 50       5 my @text = () if $^O eq "MacOS";
37              
38             # check proxy
39 1 50       5 if (defined $proxy)
40             {
41 0         0 return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST,
42             'You can not proxy with mail');
43             }
44              
45             # check method
46 1         5 my $method = $request->method;
47              
48 1 50       21 if ($method ne 'POST') {
49 1         11 return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST,
50             'Library does not allow method ' .
51             "$method for 'mailto:' URLs");
52             }
53              
54             # check url
55 0           my $url = $request->uri;
56              
57 0           my $scheme = $url->scheme;
58 0 0         if ($scheme ne 'mailto') {
59 0           return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
60             "LWP::Protocol::mailto::request called for '$scheme'");
61             }
62 0 0         if ($^O eq "MacOS") {
63 0           eval {
64 0           require Mail::Internet;
65             };
66 0 0         if($@) {
67 0           return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
68             "You don't have MailTools installed");
69             }
70 0 0         unless ($ENV{SMTPHOSTS}) {
71 0           return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
72             "You don't have SMTPHOSTS defined");
73             }
74             }
75             else {
76 0 0         unless (-x $SENDMAIL) {
77 0           return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
78             "You don't have $SENDMAIL");
79             }
80             }
81 0 0         if ($^O eq "MacOS") {
82 0 0         $mail = Mail::Internet->new or
83             return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
84             "Can't get a Mail::Internet object");
85             }
86             else {
87 0 0         open(SENDMAIL, "| $SENDMAIL -oi -t") or
88             return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR,
89             "Can't run $SENDMAIL: $!");
90             }
91 0 0         if ($^O eq "MacOS") {
92 0           $addr = $url->encoded822addr;
93             }
94             else {
95 0           $request = $request->clone; # we modify a copy
96 0           my @h = $url->headers; # URL headers override those in the request
97 0           while (@h) {
98 0           my $k = shift @h;
99 0           my $v = shift @h;
100 0 0         next unless defined $v;
101 0 0         if (lc($k) eq "body") {
102 0           $request->content($v);
103             }
104             else {
105 0           $request->push_header($k => $v);
106             }
107             }
108             }
109 0 0         if ($^O eq "MacOS") {
110 0           $mail->add(To => $addr);
111 0           $mail->add(split(/[:\n]/,$request->headers_as_string));
112             }
113             else {
114 0           print SENDMAIL $request->headers_as_string;
115 0           print SENDMAIL "\n";
116             }
117 0           my $content = $request->content;
118 0 0         if (defined $content) {
119 0 0         my $contRef = ref($content) ? $content : \$content;
120 0 0         if (ref($contRef) eq 'SCALAR') {
    0          
121 0 0         if ($^O eq "MacOS") {
122 0           @text = split("\n",$$contRef);
123 0           foreach (@text) {
124 0           $_ .= "\n";
125             }
126             }
127             else {
128 0           print SENDMAIL $$contRef;
129             }
130              
131             }
132             elsif (ref($contRef) eq 'CODE') {
133             # Callback provides data
134 0           my $d;
135 0 0         if ($^O eq "MacOS") {
136 0           my $stuff = "";
137 0           while (length($d = &$contRef)) {
138 0           $stuff .= $d;
139             }
140 0           @text = split("\n",$stuff);
141 0           foreach (@text) {
142 0           $_ .= "\n";
143             }
144             }
145             else {
146 0           print SENDMAIL $d;
147             }
148             }
149             }
150 0 0         if ($^O eq "MacOS") {
151 0           $mail->body(\@text);
152 0 0         unless ($mail->smtpsend) {
153 0           return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR,
154             "Mail::Internet->smtpsend unable to send message to <$addr>");
155             }
156             }
157             else {
158 0 0         unless (close(SENDMAIL)) {
159 0 0         my $err = $! ? "$!" : "Exit status $?";
160 0           return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR,
161             "$SENDMAIL: $err");
162             }
163             }
164              
165              
166 0           my $response = HTTP::Response->new(HTTP::Status::RC_ACCEPTED,
167             "Mail accepted");
168 0           $response->header('Content-Type', 'text/plain');
169 0 0         if ($^O eq "MacOS") {
170 0           $response->header('Server' => "Mail::Internet $Mail::Internet::VERSION");
171 0           $response->content("Message sent to <$addr>\n");
172             }
173             else {
174 0           $response->header('Server' => $SENDMAIL);
175 0           my $to = $request->header("To");
176 0           $response->content("Message sent to <$to>\n");
177             }
178              
179 0           return $response;
180             }
181              
182             1;