Postfix Perl mailing via PostDrop - perl

I'm trying to inject an email directly into the postfix queue using a perl module Mail::Postfix::Postdrop which ultilises a postfix method of allowing messages to be written directly to the postdrop directory.
There is a small amount of documentation which has enabled me to send a message successfully, however, I am confused to how I am able to set a subject and message body. An attempt to set the variable $message does little to nothing.
I must admit, I'm an apprentice to Perl at best, I would appreciate any help.
#Code which successfully sends an email:
use Mail::Postfix::Postdrop 'inject';
$message = 'test message';
inject $message, Sender => 'postmaster#mydomain.com',
Recipients => [ qw(email#someotherdomain.com) ];
Some relavant documentation:
http://annocpan.org/~PMAKHOLM/Mail-Postfix-Postdrop-0.3/lib/Mail/Postfix/Postdrop.pm

In email messages "headers" section is separated from "body" section by empty line. Just change your $message to:
$message = "Subject: This is my subject!\n\nAnd this is my message";
and you should see that you've set subject and message text. Note "\n\n", which creates empty line (double quotes are used to allow \n interpolation in $message).
Note that Mail::Postfix::Postdrop claims it accepts Email::Abstract object as a message, so you might consider using Email::Simple (or other Email::Abstract supporting class) to create your messages.

Related

Email Error: missing or malformed local part

I am noticing that I get an email from my server each time an order is placed. It looks like the customer confirmation emails are not sending.
This is part of the error message:
A message that you sent contained one or more recipient addresses that were
incorrectly constructed:
=?utf-8?B?R3Vlc3Q=?= <>: missing or malformed local part
This address has been ignored. The other addresses in the message were
syntactically valid and have been passed on for an attempt at delivery.
------ This is a copy of your message, including all the headers. ------
To: =?utf-8?B?R3Vlc3Q=?= <>
Subject: =?utf-8?B?SW50ZWxsaWdlbnQgV29ya3Nob3A6IE5ldyBPcmRlciAjIDEwMDAwMDAzMA==?=
It looks like it’s only when the user checks out without registering
=?utf-8?B?R3Vlc3Q=?= <>: missing or malformed local part
The error message is quite obvious: There should be an email address between <>, but there is none. The local part is the part of the address before the #, and as there is nothing at all here, there is no local part. Thus your server is complaining.
You have to fix whatever application is trying to send mails to <> to get rid of the error.
The email address is not written in proper format, please use <>
I really don't Understand what you are trying to do. But This is what I found out playing around with this error.
$to = "'Name of Person' <email#example.com>";
$headers = "From: ".$_POST['theirName']."<".$_POST['theirEmail'].">\r\n";
$subject = $_POST['subject'];
$messageBody = $_POST['message']."\r\n ---\n This Message was sent from ".HOME." contact form.";
mail($to,$subject,$messageBody,$headers);
Notice that around the 'Name of Person' has single quotes. If you are trying to send emails with an additional name, title or anything else in front of the emails. With the single quotes will let PHP know that it is not an email but a string, and it will add the string but be ignored as an email, not giving you the error anymore.
The header where it states from does not need to have the single quotes.
=?utf-8?B?R3Vlc3Q=?= <-This line I don't know what it supposed to be doing.
But it's not an Email on the $to/$recipient and for that reason it giving the error. Once again, must have only emails: "email1#example.com, email2#example.com" other than that: 'String' with single quotes no error will produce...

PHP Mail function used to send out unsolicited email via forms

Recently we found that someone has sent out unsolicited emails from our server. This has resulted in the server being blacklisted. I assume this is hackers using forms that have not escaped data correctly, or could it be something else as well?
We have a number of sites with their own 'contact us' type forms. I am going through all the forms and making sure the post data is being escaped. I found one form adding POST data to message without validating it first. I have just added a check before sending the email. Do you think the following will suffice, or is it better practice to escape the email post value before running it through the filter_var?
if(filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))
{
$message = $email." says hello";
$headers = "From: me#example.com";
mail('to#example.com', 'Subject', $message, $headers);
}
Should I be checking the transfer logs for header injection attacks/other attacks, if so what would I be looking for?
The best thing you can do is to check your logs to see who's sending those emails, as you probably aren't gonna check all your users' scripts.
Also, it doesn't make any sense to filter/escape/encode your own forms input (although you should definitely do it) as any of your users can user your smtp server.
Here's how you can trail your mail logs:
tail -f /var/mail/exim_mainlog
tail -f /var/log/exim_mainlog
tail -f /var/log/exim_paniclog
tail -f /var/log/exim_rejectlog

Sending email with attachment

I've a custom form (created with form API) that need send an uploaded file by email. The current form submit handler sends the email without attachment using drupal_mail().
So I'm looking for a solution to properly send email with attachment from Drupal. Mime Mail seems an overkill because HTML mail, templating and its other features are not required. But the only other alternative I see is to set the appropriate headers and serialize the attached file in the mail body when processing the mail in my hook_mail() implementation.
Did I miss anything? Is there any module to handle this?
Mimemail is the easiest solution here. Be it an overkill or not, it will allow you to get it done with a single function call.
If you insist, you may have your homemade attachment sender: base64 encode your attachment(s), add them to the mail body, add the correct headers and you're done.
You can use mime mail and force the message body to be sent in plaintext format. Here is an excerpt from the module's readme file:
USAGE
This module may be required by other modules, but is not terribly
useful by itself. Once installed, any module can send messages by
calling the mimemail() function:
$sender - a user object, text email address or an array with name, mail
$recipient - a user object, text email address or an array with name, mail
$subject - subject line
$body - body text in HTML format
$plaintext - boolean, whether to send messages in plaintext-only (default FALSE)
$headers - a keyed array with headers (optional)
$text - plaintext portion of a multipart e-mail (optional)
$attachments - array of arrays with the file's path, MIME type (optional)
$mailkey - message identifier
return - an array containing the MIME encoded message
The key thing being to set the $plaintext argument to TRUE. Now you can have your cake and eat it too.
You could always have a look at the Swift Mailer module which lets you send HTML (MIME) e-mails, e-mails with inline images and e-mails with attachments. It is also cabable of automatically generating plain text versions based on the HTML e-mail version, which in the end will let the user's e-mail client display the preferred version (HTML or plain text).
The Swift Mailer module is available on http://drupal.org/project/swiftmailer.
For the record : I'm the author and maintainer of the module.
The Webform module allows you to create a form and has a file option which can be used as an attachment. All available form components are listed on the module's manual page.
Once installed Webform will appear as a content type. Once you have saved the fundamentals, such as the title and the email to address, you will have the ability to add the required form components.
Add a component of type 'file', ensuring the 'email' (to recipient) option is ticked, and you will then be able to customize the permitted file types, extensions, sizes and upload folder.
You could use the Zend Framework.
function sendEmail($params){
ini_set('include_path', 'inc/');
require_once ('inc/Zend/Mail.php');
$mail = new Zend_Mail();
$mail->setSubject( $params['subject'] );
$mail->setBodyText( $params['bodyText'] );
$mail->setBodyHtml( $params['bodyHtml'] );
$mail->setFrom( $params['fromEmail'], $params['fromName'] );
$mail->addTo( $params['toEmail'], $params['toName'] );
// Finally, add an attachment
assert( file_exists($params['attachFile']) );
$at = $mail->addAttachment(file_get_contents($params['attachFile']));
$at->type = $params['attachType'];
$at->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
$at->filename = $params['attachName'];
$mail->send();
}

What's a good Perl OO interface for creating and sending email?

I'm looking for a simple (OO?) approach to email creation and sending.
Something like
$e = Email->new(to => "test <test#test.com>", from => "from <from#from.com>");
$e->plain_text($plain_version);
$e->html($html_version);
$e->attach_file($some_file_object);
I've found Email::MIME::CreateHTML, which looks great in almost every way, except that it does not seem to support file attachments.
Also, I'm considering writing these emails to a database and having a cronjob send them at a later date. This means that I would need a $e->as_text() sub to return the entire email, including attachments, as raw text which I could stuff into the db. And so I would then need a way of sending the raw emails - what would be a good way of achieving this?
Many thanks
You have to read the documentation more carefully, then two of your three questions would be moot.
From the synopsis of Email::MIME::CreateHTML:
my $email = Email::MIME->create_html(
You obviously get an Email::MIME object. See methods parts_set and parts_set for so called attachments.
Email::MIME is a subclass of Email::Simple. See method as_string for serialising the object to text.
See Email::Sender for sending mail.
You might check out perl MIME::Lite.
You can get the message as a string to save into a database:
### Get entire message as a string:
$str = $msg->as_string;
Email::Stuff is a nice wrapper for Email::MIME. You don't need to care about the MIME structure of the mail, the module does it for you.
Email::Stuff->from ('cpan#ali.as' )
->to ('santa#northpole.org' )
->bcc ('bunbun#sluggy.com' )
->text_body($body )
->attach (io('dead_bunbun_faked.gif')->all,
filename => 'dead_bunbun_proof.gif')
->send;
It also has as_string.

How to make an email bot that replies to users not reply to auto-responses and get itself into mail loops

I have a bot that replies to users. But sometimes when my bot sends its reply, the user or their email provider will auto-respond (vacation message, bounce message, error from mailer-daemon, etc). That is then a new message from the user (so my bot thinks) that it in turn replies to. Mail loop!
I'd like my bot to only reply to real emails from real humans. I'm currently filtering out email that admits to being bulk precedence or from a mailing list or has the Auto-Submitted header equal to "auto-replied" or "auto-generated" (see code below). But I imagine there's a more comprehensive or standard way to deal with this. (I'm happy to see solutions in other languages besides Perl.)
NB: Remember to have your own bot declare that it is autoresponding! Include
Auto-Submitted: auto-reply
in the header of your bot's email.
My original code for avoiding mail loops follows. Only reply if realmail returns true.
sub realmail {
my($email) = #_;
$email =~ /\nSubject\:\s*([^\n]*)\n/s;
my $subject = $1;
$email =~ /\nPrecedence\:\s*([^\n]*)\n/s;
my $precedence = $1;
$email =~ /\nAuto-Submitted\:\s*([^\n]*)\n/s;
my $autosub = $1;
return !($precedence =~ /bulk|list|junk/i ||
$autosub =~ /(auto\-replied|auto\-generated)/i ||
$subject =~ /^undelivered mail returned to sender$/i
);
}
(The Subject check is surely unnecessary; I just added these checks one at a time as problems arose and the above now seems to work so I don't want to touch it unless there's something definitively better.)
RFC 3834 provides some guidance for what you should do, but here are some concrete guidelines:
Set your envelope sender to a different email address than your auto-responder so bounces don't feed back into the system.
I always store in a database a key of when an email response was sent from a specific address to another address. Under no circumstance will I ever respond to the same address more than once in a 10 minute period. This alone stopped all loops, but doesn't ensure nice behavior (auto-responses to mailing lists are annoying).
Make sure you add any permutation of header that other people are matching on to stop loops. Here's the list I use:
X-Loop: autoresponder
Auto-Submitted: auto-replied
Precedence: bulk (autoreply)
Here are some header regex's I use to avoid loops and to try to play nice:
/^precedence:\s+(?:bulk|list|junk)/i
/^X-(?:Loop|Mailing-List|BeenThere|Mailman)/i
/^List-/i
/^Auto-Submitted:/i
/^Resent-/i
I also avoid responding if any of these are the envelop senders:
if ($sender eq ""
|| $sender =~ /^(?:request|owner|admin|bounce|bounces)-|-(?:request|owner|admin|bounce|bounces)\#|^(?:mailer-daemon|postmaster|daemon|majordomo|ma
ilman|bounce)\#|(?:listserv|listsrv)/i) {
That really sounds like something that's probably available as a module from CPAN, but I didn't find anything clearly relevant in five minutes of searching. Mail::Lite::Mbox::Processor looks like it might do what you want:
Mail::Lite::Message::Matcher is a
framework for automated mail
processing. For example you have a
mail server and you have a need to
process some types of incoming mail
messages automatically. For example,
you can extract automated
notifications, invoices, alerts etc.
from your mail flow and perform some
tasks based on content of those
messages.
but its docs are sparse enough that it isn't immediately obvious whether it provides those example functions itself or if you have to provide the code to drive them.
In any case, though, if you haven't already checked CPAN, that's where I would start if I wanted to do something like this.
My answer here only deals with bounces which is more straightforward.
Using DSN (Delivery Status Notification) identifier will help you detect a DSN/bounced message. It should go to Return-Path and not Reply-To.
Here's a sample of a typical DSN message. The header information includes the message id, content type has specific values (delivery-status) etc.
Not able to provide you any codes in perl, just my 2 cents of idea.
PS: Do note that not all mail servers or MTA conforms to this, but I guess most do.
There should be a standard way of dealing with this, but the problem is that you'd have to assume that systems that send auto-replies comply to that standard, when most the time, they just don't.
How do you get the address that you reply to? I hope you aren't using the From: header. Check the Reply-to: header first and if that doesn't exist, use the Return-path:.
But whatever you do, you will simply have to keep a log of what you sent to whom and throttle your bot to some sensible value of messages per time.