Guest User

Untitled

a guest
Mar 9th, 2018
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.23 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. #
  4. # Simple utility to send authenticated messages.
  5. #
  6. # Copyright (C) 2007 Entercore, Ltda.
  7. # Rodrigo Madera
  8. #
  9.  
  10. use Net::SMTP;
  11. use MIME::Base64;
  12. use Getopt::Long;
  13. use IO::Socket;
  14.  
  15. %accounts = ();
  16. $accounts { "XXX" } = "XXXPASS";
  17. $accounts { "YYY" } = "YYYPASS";
  18.  
  19. $account = "";
  20. $forcedFrom = "";
  21. $daemon = 0;
  22. $help = 0;
  23.  
  24. sub printUsageAndExit {
  25. print STDERR "Usage:\n";
  26. print STDERR "\n";
  27. print STDERR "ec-mailer <--account=acct> [--force-from=email@address.com]\n";
  28. print STDERR "ec-mailer --daemon\n";
  29. print STDERR "\n";
  30. print STDERR "\taccount { twiki, scarab, etc }\n";
  31. print STDERR "\tforce-from Force the FROM field to be this account.\n";
  32. print STDERR "\tdaemon Run a SMTP server on this machine.\n";
  33. print STDERR "\thelp This usage help text.\n";
  34. print STDERR "\n";
  35. exit -1;
  36. }
  37.  
  38. sub _fixLineLength {
  39. my( $addrs ) = @_;
  40. # split up header lines that are too long
  41. $addrs =~ s/(.{60}[^,]*,\s*)/$1\n /go;
  42. $addrs =~ s/\n\s*$//gos;
  43. return $addrs;
  44. }
  45.  
  46. sub sendEmail {
  47. my($username, $password, $text) = @_;
  48.  
  49. my $from = '';
  50. my @to = ();
  51.  
  52. my ( $header, $body ) = split( "\n\n", $text, 2 );
  53. my @headerlines = split( /\r?\n/, $header );
  54. $header =~ s/\nBCC\:[^\n]*//os; #remove BCC line from header
  55. $header =~ s/([\n\r])(From|To|CC|BCC)(\:\s*)([^\n\r]*)/$1 . $2 . $3 . _fixLineLength( $4 )/geois;
  56. $text = "$header\n\n$body"; # rebuild message
  57.  
  58. # extract 'From:'
  59. if ($forcedFrom ne "") {
  60. $from = $forcedFrom;
  61. } else {
  62. my @arr = grep( /^From: /i, @headerlines );
  63. if( scalar( @arr ) ) {
  64. $from = $arr[0];
  65. $from =~ s/^From:\s*//io;
  66. $from =~ s/.*<(.*?)>.*/$1/o; # extract "user@host" out of "Name <user@host>"
  67. } unless( $from ) {
  68. print STDERR "ERROR: Can't send mail, missing 'From:'\n";
  69. return;
  70. }
  71. }
  72.  
  73. # extract @to from 'To:', 'CC:', 'BCC:'
  74. @arr = grep( /^To: /i, @headerlines );
  75. my $tmp = '';
  76. if( scalar( @arr ) ) {
  77. $tmp = $arr[0];
  78. $tmp =~ s/^To:\s*//io;
  79. @arr = split( /,\s*/, $tmp );
  80. push( @to, @arr );
  81. }
  82.  
  83. @arr = grep( /^CC: /i, @headerlines );
  84. if( scalar( @arr ) ) {
  85. $tmp = $arr[0];
  86. $tmp =~ s/^CC:\s*//io;
  87. @arr = split( /,\s*/, $tmp );
  88. push( @to, @arr );
  89. }
  90.  
  91. @arr = grep( /^BCC: /i, @headerlines );
  92. if( scalar( @arr ) ) {
  93. $tmp = $arr[0];
  94. $tmp =~ s/^BCC:\s*//io;
  95. @arr = split( /,\s*/, $tmp );
  96. push( @to, @arr );
  97. }
  98.  
  99. if (!(scalar(@to))) {
  100. print STDERR "ERROR: Can't send mail, missing recipient\n";
  101. return;
  102. }
  103.  
  104. return undef unless( scalar @to );
  105.  
  106. # Change SMTP protocol recipient format from
  107. # "User Name <userid@domain>" to "userid@domain"
  108. # for those SMTP hosts that need it just that way.
  109. foreach (@to) {
  110. s/^.*<(.*)>$/$1/;
  111. }
  112.  
  113. $smtp = Net::SMTP->new(
  114. 'smtp.entercore.com' ,
  115. Hello => "client.entercore.com",
  116. Timeout => 10,
  117. Debug => 1,
  118. ) || die "Couldn't connect to mail server.\n";
  119.  
  120. my $status = '';
  121.  
  122. $smtp->rawdatasend("AUTH LOGIN\n");
  123. $smtp->response();
  124. $smtp->rawdatasend(encode_base64($username));
  125. $smtp->response();
  126. $smtp->rawdatasend(encode_base64($password));
  127. $smtp->response();
  128.  
  129. $smtp->mail($from) || die $mess.$smtp->message;
  130. $smtp->to(@to, { SkipBad => 1 }) || die $mess.$smtp->message;
  131.  
  132. $smtp->data($text) || die $mess.$smtp->message;
  133. $smtp->quit();
  134. }
  135.  
  136. # Implementation of a listening server...
  137. $client;
  138. sub mailServer {
  139. my $server = IO::Socket::INET->new(LocalPort => 25,
  140. Type => SOCK_STREAM,
  141. Reuse => 1,
  142. Listen => 10)
  143. || die "ERROR: Couldn't open server on port $port";
  144.  
  145. STDOUT->autoflush(1);
  146.  
  147. while ($client = $server->accept()) {
  148. $client->send("220 Entercore Mailer Daemon\r\n");
  149.  
  150. my $running = 1;
  151. while ($running) {
  152. my $command = receiveLine();
  153. print ">>> $command\n";
  154. if (!$command || $command eq "QUIT") {
  155. sendLine("221 Goodbye.");
  156. $client->close();
  157. last;
  158. } elsif ($command =~ /^MAIL FROM:/) {
  159. $from = $command;
  160. $from =~ s/^MAIL FROM:\s*//io;
  161. $from =~ s/.*<(.*?)>.*/$1/o;
  162. sendLine("250 Proceed.");
  163. } elsif ($command =~ /^RCPT TO:/) {
  164. (undef, $to) = split(/:/, $command, 2);
  165. sendLine("250 Proceed.");
  166. } elsif ($command eq "DATA") {
  167. sendLine("354 Ready for data");
  168. $data = receiveData();
  169. sendLine("250 Proceed.");
  170. } else {
  171. sendLine("250 Proceed.");
  172. }
  173. }
  174.  
  175. ($account, undef) = split(/@/, $from, 2);
  176. if (!exists($accounts{$account})) {
  177. print STDERR "ERROR: Account not found: ${account}\n";
  178. } else {
  179. print "From {$from}\n";
  180. print "To {$to}\n";
  181. print "Data {$data}\n";
  182. print "username=$username\n";
  183.  
  184. $username = $account."=entercore.com";
  185. $password = $accounts{$account};
  186. $input = "MAIL FROM: $account@entercore.com\r\n";
  187. $input .= "RCPT TO: $to\r\n";
  188. $input .= "DATA\r\n";
  189. $input .= "$data";
  190. $input .= "QUIT\r\n";
  191.  
  192. print "input={$input}\n";
  193. sendEmail($username, $password, $input);
  194. }
  195. }
  196. }
  197.  
  198. sub sendLine {
  199. my $message = $_[0];
  200. $client->send("$message\r\n");
  201. print "<<< $message\n";
  202. }
  203.  
  204. sub receiveLine {
  205. my $line;
  206. $client->recv($line, 1024);
  207. return decodeLine($line);
  208. }
  209.  
  210. sub receiveData {
  211. my $fullLine;
  212. my $line;
  213. while ($fullLine !~ /[\r\n]\.[\r\n]/) {
  214. $client->recv($line, 255);
  215. $fullLine .= $line;
  216. }
  217.  
  218. return $fullLine;#decodeLine($fullLine);
  219. }
  220.  
  221. sub decodeLine {
  222. my $line = $_[0];
  223.  
  224. if ($echo) {
  225. my $visline = $line;
  226. $visline =~ s/\r/\\r/g; # make \r visible
  227. $visline =~ s/\n/\\n/g; # make \n visible
  228. $visline =~ s/(\\r|\\n)([^\\])/$1\n<$2/g; # break line after '\r', '\n', '\r\n, or '\n\r'
  229. $visline =~ s/(\\r\\n)(\\r\\n)/$1\n<$2/g; # break line between adjacent sets of '\r\n'
  230. print "<$visline\n";
  231. }
  232. $line =~ s/[\r\n]//g;
  233. return $line;
  234. }
  235.  
  236. ##
  237. ## main()
  238. ##
  239.  
  240. GetOptions(
  241. 'account=s' => \$account,
  242. 'forced-from=s' => \$forcedFrom,
  243. 'daemon!' => \$daemon,
  244. 'help!' => \$help,
  245. ) or printUsageAndExit();
  246.  
  247. if ($help || ($account eq "" && !$daemon)) {
  248. printUsageAndExit();
  249. }
  250.  
  251. if ($daemon) {
  252. mailServer();
  253. exit 0;
  254. }
  255.  
  256. if (!exists($accounts{$account})) {
  257. print STDERR "ERROR: Account not found\n";
  258. exit -1;
  259. }
  260.  
  261. $username = $account."=entercore.com";
  262. $password = $accounts{$account};
  263.  
  264. $input = join("", <STDIN>);
  265. sendEmail($username, $password, $input);
Add Comment
Please, Sign In to add comment