Send mail without MTA, GMail, etc

emailemail-serversmtp

Why doesn't it seem to be possible to send mails from the command line without any kind of SMTP server? All solutions that I found either use sendmail, postfix, etc. (those are SMTP servers as far as I understand it) or send it over GMail or some other provider (which needs authentication). Why can't an application just connect directly to the target mail server? For example, if I want so send a mail to user@test.com, why can't an application just connect to test.com and deliver the mail directly without any kind of other server involved? Sure, it would be marked as spam, but I don't care about that. Did I misunderstand the SMTP protocol, did I just not find the right application or did really just no one bother to write such an application?

Best Answer

did really just no one bother to write such an application?

Now they did!

As a follow up to my other answer where I suggest writing a Python script, I have now written a very basic python 3 script that can do this for you. I have tested it on both Linux (2 different distributions) and Windows, and it definitely sends mail from both to my gmail account, which yes, does end up in the spam folder!

It cheats a little by using nslookup -type=mx <recipient_domain_name> 8.8.8.8 to do the nslookup (8.8.8.8 is Google's public DNS server), but the script still works on both Windows and Linux - the results are just parsed slightly differently. The reason for this "cheat" is to save you installing a third party python library, although it does assume you have the nslookup command available in your path - which it usually is.

It would be fairly easy to add extra functionality for attachments, friendly names in To: From: message headers, etc. Also, all the mx servers that are found by DNS are stored in a list in priority order, but the script only attempts to send to the first one. It would be fairly easy to improve the script so that it checks the others in priority order in case of failure to reach the first one.

Usage: direct_mail_sender.py recipient@domain.com from@originator.com "msg subject" "msg body"

Enclosing the subject and body in "double quotes" ensures that you can include spaces between the words.

#!/usr/bin/python3
import subprocess, sys, smtplib

mx_records = []
mx_values = {'pref' : 0, 'serv' : ''}

if len(sys.argv) < 5:
    print('\nUsage:\ndirect_mail_sender.py recipient@domain.com from@originator.com "msg subject" "msg body"\n')
    exit()

recipient = sys.argv[1]
domain = recipient.split("@")[1]
originator = sys.argv[2]
subject = sys.argv[3]
body = sys.argv[4]

print("From:   " + originator)
print("To:     " + recipient)
print("Subject " + subject)
print("Body    " + body)

p = subprocess.Popen('nslookup -type=mx ' + domain + ' 8.8.8.8', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    line = line.decode().lower()
    if line.find("mail exchanger") !=-1 :
        for char in line:
            if str(char) in "\r\n\t":
                line = line.replace(char, '')
        if line.find("mx preference") !=-1 :
            mx_parse = line.replace(' ', '').split(",")
            mx_values['pref'] = int(mx_parse[0].split("=")[1])
            mx_values['serv'] = mx_parse[1].split("=")[1]
        else:
            mx_parse = line.split(" = ")[1].split(" ")
            mx_values['pref'] = int(mx_parse[0])
            mx_values['serv'] = mx_parse[1]
        mx_records.append(mx_values.copy())

retval = p.wait()

def mx_pref_sortvalue(record):
    return record['pref']
mx_records=sorted(mx_records, key=mx_pref_sortvalue)

server = mx_records[0]['serv']

print("\nSending mail to: " + recipient + " via first priority MX server: " + server)

smtp_send = smtplib.SMTP(server, 25)
smtp_send.sendmail(originator, recipient, "From: " + originator + "\nTo: " + recipient + "\nSubject:" + subject + "\n\n" + body)
smtp_send.quit()