Quick Python Mailer

import sys,smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

msg = MIMEMultipart()
msg['From'] = 'root@domain.ad'
msg['To'] = 'user@domain.com'
msg['Subject'] = 'Process finished -' + sys.argv[1]
message = 'here is the email'
msg.attach(MIMEText(message))

mailserver = smtplib.SMTP('mail.domain.com',25)
# identify ourselves to smtp gmail client
mailserver.ehlo()
# secure our email with tls encryption
mailserver.starttls()
# re-identify ourselves as an encrypted connection
mailserver.ehlo()

mailserver.sendmail('root@domain.ad','user@domain.com',msg.as_string())

mailserver.quit()

** This script need to be optimized. I am duplicating from and to fields

Postfix Filter Outbound Email

In a previous article I wrote about using Sendmail to block outbound email and at the same time allow email to specific domains or specific email addresses.

As I explained Sendmail could handle blocking and selective relaying to domains effectively but could not easily handle adding specific email addresses to the mix.  Below is a quick howto on setting up Postfix on Solaris 11 and configuring the blocking as required.

# svcadm disable svc:/network/smtp:sendmail

# pkg install developer/gcc-45
# pkg install library/gnutls

** Note that the postfix-install script kicks off during gmake install. You will note I used /usr/local for install_root since I do not want to taint anything on the regular paths. However that does not work very well. I ended up having to move quite a few folders and files from /usr/local/usr/local to /usr/local. I will have to try this again and see if using / for install_root is acceptable for keeping things separate and not taint system paths.

# wget http://postfix.bbnx.net/postfix-release/official/postfix-2.10.2.tar.gz
# gzip -d postfix-2.10.2.tar.gz
# tar xf postfix-2.10.2.tar
# pwd
/usr/src/postfix-2.10.2

# gmake clean
# gmake makefiles MAKE=gmake CCARGS='-DNO_NIS -DUSE_TLS -lssl -lcrypto'
# gmake
# gmake install
...
/bin/sh postfix-install
...
install_root: [/] /usr/local/
tempdir: [/usr/src/postfix-2.10.2]
config_directory: [/etc/postfix]
command_directory: [/usr/sbin] /usr/local/sbin
daemon_directory: [/usr/libexec/postfix] /usr/local/libexec/postfix
data_directory: [/var/lib/postfix]
html_directory: [no]
mail_owner: [postfix]
mailq_path: [/usr/bin/mailq] /usr/local/bin/mailq
manpage_directory: [/usr/local/man]
newaliases_path: [/usr/bin/newaliases] /usr/local/bin/newaliases
queue_directory: [/var/spool/postfix]
readme_directory: [no]
sendmail_path: [/usr/lib/sendmail]
setgid_group: [postdrop]
...

Setup user, group and configure Postfix:

# groupadd postdrop
# useradd -d /export/home/postfix -s /usr/bin/bash -m postfix
80 blocks

# mkdir /etc/postfix
# pwd
/etc/postfix

# grep -v ^# main.cf | grep ".$"
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
unknown_local_recipient_reject_code = 550
mynetworks = 10.2.0.0/16, 127.0.0.0/8
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
 ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/lib/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = no
inet_protocols = ipv4
header_checks = pcre:/etc/postfix/header_checks

# tail -4 header_checks
/^To: .*@domain1\.com/ FILTER smtp:mail.domain1.com
/^To: .*@domain2\.com/ ACCEPT
/^To: user@domain3\.com/ ACCEPT
/^To: .*/ REJECT

***  ACCEPT is not really a defined ACTION but for me this works.  I will have to look into this closer.  Maybe action should be INFO.

*** Note that domain1 needed to relay to a specific internal host whereas domain2 is an example of direct forwarding to the Internet.

Fix the /usr/local/usr/local installation. Should do a re-install and fix this.

mv /usr/local/etc/postfix/* /etc/postfix/

mkdir /usr/local/sbin
mkdir /usr/local/libexec/
mkdir /usr/local/libexec/postfix
mkdir /var/spool/postfix

mv /usr/local/usr/local/libexec/ /usr/local/
mv /usr/local/usr/local/libexec/postfix/postfix-script /usr/local/libexec/postfix/
mv /usr/local/usr/local/sbin/post* /usr/local/sbin/
mv /usr/local/usr/local/libexec/postfix/* /usr/local/libexec/postfix/

chgrp postdrop /usr/local/sbin/postqueue
chgrp postdrop /usr/local/sbin/postdrop
chmod +x /usr/local/sbin/postqueue
chmod +x /usr/local/sbin/postdrop

chmod +s /usr/local/sbin/postqueue
chmod +s /usr/local/sbin/postdrop

Start and test:

# /usr/local/sbin/postfix start

# tail -f /var/log/syslog

TODO: Redo and fix installation and add to Solaris SMF.

Update 12.30.13:

More testing showed that this solution does not work well with mailing lists ie multiple recipients in the To: field.   After playing with a lot of different options I finally liked the idea of running multi-postfix.  In short that entails a 1st instance accepting mail on port 25 and then split the message into multiple messages and feed it to the 2nd instance on 127.0.0.1:10026 or whatever addresses and ports you prefer.  The trick is to use default_destination_recipient_limit = 1 option on the frontend instance.  This seemed like an elegant solution, but for me my header checks were still not working like I want.  After a lot of fiddling I decided to use a different approach.  At some point I will document the two postfix instance solution since it might fit a lot of use cases.

The solution that I finally used was accepting mail on port 25 with python smtplib and then sanitizing the list before injecting back into sendmail on say127.0.0.1:10026.  The article here:  <>

 

Sendmail Filter Outbound Email

In some projects I need to block outbound email but still allow email to a select few domains (or even select few addresses).

As Sendmail comes standard on a lot of Unix operating systems I show here how to set this up.  Sendmail handles some of these requirements pretty easy.  Additional options like filtering through procmail as well as using Sendmail milters are also good options but not very easy to configure.   I did not check but I suspect Linux comes with packages that would make installing python or perl Milter modules easy.

Since Milter packages are not readily available on Solaris and I am focusing on Solaris for this particular project I will use Postfix to meet all the requirements instead of Sendmail + procmail / Milters.  I will follow up with a Postfix specific article later since it does better at filtering and relaying than Sendmail.

My use case:

  1. First block ALL outbound email
  2. Allow ALL outbound email to two specific domains
  3. Allow email to very specific email addresses not included in above mentioned two domains

Sendmail handled #1 and #2 pretty easily but it gets overly complicated to allow #1, #2 and #3 at the same time.  Below is the configuration for #1 and #2 on Solaris 11.

# pwd
/etc/mail/cf/cf

# cp sendmail.mc myhost.mc

# cat myhost.mc
divert(-1)
... snip ...
divert(0)dnl
VERSIONID(`sendmail.mc (Sun)')
OSTYPE(`solaris11')dnl
DOMAIN(`solaris-generic')dnl
dnl DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
DAEMON_OPTIONS(`Port=smtp,Addr=10.1.10.52, Name=MTA')dnl
MASQUERADE_AS(`mydomain.com')
FEATURE(masquerade_envelope)
FEATURE(`access_db')
FEATURE(`mailertable')
MAILER(`local')dnl
MAILER(`smtp')dnl

# /usr/ccs/bin/m4 ../m4/cf.m4 myhost.mc > /etc/mail/sendmail.cf

** You probably don’t need the access feature and local mailer above for this specific configuration. But access might provide more granularity around permissions that might help you.

Setup mailertable. Remember use tabs between left and right columns.

# pwd
/etc/mail

# cat mailertable
domain1.com             relay:[mail.domain1.com]
domain2.com             esmtp:%0
.                       local:nobody

# makemap hash mailertable < mailertable

** Note above domain1 needed to be passed off to a specific relay on the internal network and domain2 needed to be passed on direct to the Internet.

On Solaris set local_only to false and start senmdail service.

# svccfg -s svc:/network/smtp:sendmail setprop config/local_only = false
# svcadm disable svc:/network/smtp:sendmail
# svcadm enable svc:/network/smtp:sendmail

From client setup a smarthost poitning to new server we configured and then test as follow:

# cat /tmp/test.eml
To: user@domain1.com
Subject: MAILHOST TEST -&gt; via domain1
From: luser@domain.com

body....

# sendmail -d7.99 -d38.99 -vt &lt; /tmp/test.eml

Monitor var/log/syslog:

Dec 27 14:44:34 myhost sendmail[6774]: [ID 801593 mail.info] rBRJiYFA006774: from=&lt;root@myclient&gt;, size=554,, nrcpts=1, msgid=&lt;201312271946.rBRJkgq8001045@myclient&gt;, proto=ESMTP, daemon=MTA, relay=myclient [10.1.11.62]
Dec 27 14:44:35 myhost sendmail[6776]: [ID 702911 mail.info] STARTTLS=client, relay=mail.arbonne.com., version=TLSv1/SSLv3, verify=FAIL, cipher=AES128-SHA, bits=128/128
Dec 27 14:44:36 myhost sendmail[6776]: [ID 801593 mail.info] rBRJiYFA006774: to=&lt;user@domain1.com&gt;, delay=00:00:02, xdelay=00:00:02, mailer=relay, pri=120554, relay=mail.domain1.com. [10.10.1.130], dsn=2.0.0, stat=Sent (&lt;201312271946.rBRJkgq8001045@usla-psag-ag01.prd.asg.ad&gt; [InternalId=15753532] Queued mail for delivery)