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