I have a Perl script that sends simple HTML emails to users with status updates and a link to more information. I'm creating mail with Net::SMTP and sending mail using smtp-relay.gmail.com. It has been working great for years.
In the last month, the emails stopped appearing - just gone with no errors and not in SPAM. Hours of troubleshooting later, I've narrowed the problem down to Gmail silently dropping emails that contain my specific URL.
http://DOMAIN/cgi-bin/requests/single_request.pl?requestid=111111
I changed one character and POOF! working again.
http://DOMAIN/cgi-bin/requests/single-request.pl?requestid=111111
I know this is a vague question, but what is going on? The workaround is fine, but I sure didn't learn anything about the root cause.
#!c:\strawberry\perl\bin -w
use strict;
use warnings;
use Net::SMTP;
use Net::Config;
# use this function to send email
#
# example:
#
# send_mail("RECIPIENT\#DOMAIN", "SUBJECT HERE", "BODY HERE");
sub send_mail{
my $recipient = shift;
my $subject = shift;
my $body = shift;
# connect to an SMTP server
my $smtp = Net::SMTP->new("smtp-relay.gmail.com", Debug => 0, Timeout => 30, Hello => 'REDACTED') or die "SMTP Connection Failed: smtp-relay.gmail.com";
# sender's address here
$smtp->mail('REDACTED');
# recipient"s address
$smtp->to($recipient);
# Start the mail
$smtp->data();
# Send the header.
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-Type: text/html; charset=\"UTF-8\" \n");
$smtp->datasend("To: $recipient . \n");
$smtp->datasend("From: REDACTED\n");
$smtp->datasend("Reply-to: REDACTED\n");
$smtp->datasend("Subject: $subject \n");
$smtp->datasend("\n");
# Send the body.
$smtp->datasend($body);
# Finish sending the mail
$smtp->dataend();
# Close the SMTP connection
$smtp->quit();
}
1;
Related
I have this script to send email. Everything works except that after the email is sent I receive the error below. It has to be something simple I am missing. I checked and cgi file is 755 and since it gets to the sub and executes its got to be coder error. Any help greatly appreciated.
Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request. More information about this error may be available in the server error log. Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
The error in the server log is:
[Tue Jan 17 16:00:23.475272 2023] [cgi:error] [pid 230679] [client 69.90.223.10:35014] End of script output before headers: test3.cgi
Here is the code I am using, Perl CGI on Linux
#!/usr/bin/perl -Tw
# use warnings;
use strict;
use Net::SMTP;
send_mail('mail.xxxxxxx.com', # Host
'order#xxxxxxxxx.com', #From
'yyyyyyy#gmail.com', #to
'Just a test, from mail.xxxxxx.com please ignore', #Message body
"Testing mail server email.\n" # Subject
);
exit;
sub send_mail {
my ($SMTP_HOST, $from, $to_addr, $body, $subject, $msg) = #_;
$msg = "MIME-Version: 1.0\n"
. "From: $from\n"
. "To: " . ( ref($to_addr) ? join(';', #$to_addr) : $to_addr ) . "\n"
. "Subject: $subject\n\n" # Double \n
. $body;
#
# Open a SMTP session
#
my $smtp = Net::SMTP->new( $SMTP_HOST,
Debug => 0, # Change to a 1 to turn on debug messages
Port => 587,
);
die("SMTP ERROR: Unable to open smtp session.\n")
if(!defined($smtp) || !($smtp));
die("Failed to set FROM address\n")
if (! ($smtp->mail( $from ) ) );
die("Failed to set receipient\n")
if (! ($smtp->recipient( ( ref($to_addr) ? #$to_addr : $to_addr ) ) ) );
$smtp->data( $msg );
$smtp->quit;
}
Checked File attributes they are 755
Since it ran the code an performed the send email the Char set should be correct
Being new to Perl not sure what else to check
This isn't a CGI program. You send no response for the request. Since there is no response (not even an invalid one), the script exits with nothing sent to standard output. The server realizes this is a problem, creates the 500 server error response, and adds to the error log that the script output ended before headers, which is the first thing the server expected to see.
You might want to start with a basic CGI tutorial to see how CGI works.
But, also realize that sending mail through a CGI program is a very 1990s thing to do. We don't typically do that anymore because we all figured out that letting anyone trigger mail through a public server was a bad idea.
I am trying to send my first email (from a windows machine) with Perl, but I am getting an error:
SMTP Failed to connect to mail server: at emailer2.pl line 18 (msg->send;)
I am totally new to Perl so any help would be greatly appreciated. Has anyone encountered this problem before? I have searched for the error but I had no luck finding my exact problem.
Thanks so much for your help!
CODE:
#!/usr/bin/perl
use MIME::Lite;
$to = 'myemail#gmail.com';
$cc = 'myemail#gmail.com';
$from = 'myemail#gmail.com';
$subject = 'Test Email';
$message = 'This is test email sent by Perl Script';
$msg = MIME::Lite->new(
From => $from,
To => $to,
Cc => $cc,
Subject => $subject,
Data => $message
);
$msg->send;
print "Email Sent Successfully\n";
It means you don't have a mail server running on your machine. You need to install one and make sure it is running.
You may also use another mail server setting default parameters before sending the message
MIME::Lite->send('smtp', "smpt.example.org", Timeout=>60, SSL=>1,
AuthUser=>"myself", AuthPass=>"mysecret");
Take a look at MIME::Lite sending section.
I have a form on my page. When the user hits the Send button - it's supposed to send an email with the details he entered in the form. Up until recently the form was hosted on a Linux server and I had no problem with it - the mail was sent and received. Recently I had to move to shared Windows server and since the move the mail is not sent. Here's the code that supposed to send the mail:
function send_contact_form($strName, $strEmail, $strPhone, $strMessage)
{
$to = 'mymail#mysite.com';
$subject = 'From the site';
$message = '<html lang="HE">
<head>
<title>
'.$subject.'
</title>
</head>
<body style="text-align:right; direction:rtl; font-family: Arial;">
Name: '.$strName.'<br>Email: '
.$strEmail.'<br>Phone: '.$strPhone
.'<br><br>Message: <br>'.$strMessage.'
</body>
</html>';
$email = $strEmail;
$header = 'MIME-Version: 1.0' . "\r\n";
$header .= 'Content-type: text/html; charset=UTF-8' . "\r\n";
$header .= "From: $email\r\nReply-To: $email" . "\r\n";
mail($to, $subject, $message, $header);
}
In a windows environment PHP uses SMTP insted of the Linux binary sendmail (or replacement)
You need to edit php.ini according to this page to be able to send e-mail via the mail() function.
On Linux, PHP uses an application called sendmail. Of course there is no similar applicaion on Windows. As php.ini file says, to be able to work with mail function, you need to setup mail server coordinates. If You don't have mail server, it is not possible to send emails from PHP. Of course You could use some external server like gmail.
I am unable to send a mail using MIME::Lite. While sending from my desktop it will through the below errors.
Error: "SMTP Failed to connect to mail server: Bad file descriptor"
I am using the below mentioned code.
use strict;
use MIME::Lite;
use Net::SMTP;
my $from_address = "no-reply#host.com";
my $to_address = "madhan#host.com";
my $cc_address = "madhan#host.com";
my $subject = "Test mail";
my $message_body = "Madhan test mail";
my $namer="madhankumar";
my $regards="Madhan M";
print " Sending mail from $from_address to $to_address \n";
my $person_name=ucfirst($namer).",";
my $mail_host = 'mail1.somehost.com';
my $msg = MIME::Lite->new (
From => $from_address,
To => $to_address,
Cc => $cc_address,
Subject => $subject,
Type =>'multipart/mixed'
) or die "Error creating multipart container: $!\n";
$msg->attach (
Type => 'TEXT',
Data => "Dear $person_name\n\n".$message_body."\n\nRegards,\n$regards"
) or die "Error adding the text message part: $!\n";
MIME::Lite->send('smtp', $mail_host, Timeout=>60);
$msg->send;
The above code is working fine while the mail server is connected with LAN. While using the code in remote system the error has been thrown as mentioned in below
"SMTP Failed to connect to mail server: Bad file descriptor".
May I know the reason.. Is the code run in remote system. If not what are the change I have made the code.. Please share your solutions....
Thanks in advance...
Note: I am developing this in Windows XP
The variables do not contain what you think they contain. If you had switched on warnings, you would have noticed this on your own.
$ perl -e'use warnings; my $from_address = "no-reply#host.com";'
Possible unintended interpolation of #host in string at -e line 1.
Name "main::host" used only once: possible typo at -e line 1.
The remedy is to use single quotes to delimit those strings.
I have been using Email::Sender with Email::Sender::Transport::SMTP::TLS send email using a STARTTLS enabled relay. The relay has recently changed to using X.509 certificates for authentication. However I note that Email::Sender::Transport::SMTP::TLS has no option to point to my certificate. Neither does Net::SMTP::TLS on which Email::Sender::Transport::SMTP::TLS is based.
Can someone suggest a solution? Another module perhaps that will allow me to authenticate using a certificate.
Thank you
Checking the dependency tree: Email::Sender::Transport::SMTP::TLS ==> Net::SMTP::TLS::ButMaintained ==> IO::Socket::SSL ==> Net::SSLeay
Both IO::Socket::SSL and Net::SSLeay supporting the X.509 client certificates. So Net::SMTP::TLS::ButMaintained and Email::Sender::Transport::SMTP::TLS should be enhanced to support client certificates. A proper way should update both modules to allow the SSL_key|SSL_key_file and SSL_cert|SSL_cert_file parameters.
Here is a quick dirty one -- you need to create modified Net::SMTP::TLS::ButMaintained and keep it locally.
# modify the Net::SMTP::TLS::ButMaintained;
# built a private version which have client certificates
sub starttls {
my $me = shift;
$me->_command("STARTTLS");
my ( $num, $txt ) = $me->_response();
if ( not $num == 220 ) {
croak "Invalid response for STARTTLS: $num $txt\n";
}
if (
not IO::Socket::SSL::socket_to_SSL(
$me->{sock},
SSL_version => "SSLv3 TLSv1",
### private changes begin: append following two lines.
SSL_use_cert => 1,
SSL_cert_file => "path_to/your/certificate_file.pem",
SSL_key_file => "path_to/your/private_key_file.pem"
### private changes end:
)
)
{
croak "Couldn't start TLS: " . IO::Socket::SSL::errstr . "\n";
}
$me->hello();
}
Please leave the User and Password parameter as blank.
Good luck!
for completeness sake, Net::SMTP can do this if IO::Socket::SSL is available (don't ask me since when, but I know it works with recent versions of both modules).
Code:
use strict;
use warnings;
use Net::SMTP;
my $smtp = Net::SMTP->new(
Host => 'host.domain.tld',
Hello => 'hi there',
Port => 587,
Timeout => 5,
Debug => 4,
);
$smtp->starttls(
SSL_cert_file => "/path/to/crt",
SSL_key_file => "/path/to/key",
);
$smtp->mail("user\+perl\#domain\.nl\n");
$smtp->to("user\#otherdomain\.tld\n");
$smtp->data;
$smtp->datasend("From: Your Name <user\#domain.tld>\n");
$smtp->datasend("To: Recipient <user\#otherdomain.tld>\n");
$smtp->datasend("Subject: certificate based relay testing\n");
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-Type: text/plain; charset=us-ascii\n");
$smtp->datasend("X-Mailer: Net::SMTP IO::Socket::SSL\n");
$smtp->datasend( "X-mydate: " . localtime() . "\n" );
$smtp->datasend("\n");
$smtp->datasend("testing again\n");
$smtp->dataend;
$smtp->quit;
The host must exactly match the subject in the certificate, or it will not validate.
I assume your system trusts the certificate authority of the relay server, otherwise you need to fix that too.