I have setup a local SMTP server with aiosmtpd where I received emails after setting the proper DNS records:
mail.mydomain.com A 1 minute 1.2.3.4
mydomain.com MX 1 minute 10 mail.mydomain.com.
Just running aiosmtpd in the command line is enough to receive emails:
python.exe -m smtpd -c DebuggingServer -n 0.0.0.0:25
The problem is now sending emails which for whatever reason seems not to work. I have set the SPF record this way:
mydomain.com TXT 1 minute "v=spf1 a mx include: mydomain.com ~all"
I have tried with this too:
mydomain.com TXT 1 minute "v=spf1 ip4:1.2.3.4 ~all"
I'm using this code to send the email while the SMTP server is running:
import smtplib
sender = 'from#mydomain.com'
receivers = ['to#mydomain.com']
message = """From: From Person <from#mydomain.com>
To: To Person <to#mydomain.com>
Subject: SMTP e-mail test
This is a test e-mail message.
"""
try:
smtpObj = smtplib.SMTP('127.0.0.1')
smtpObj.sendmail(sender, receivers, message)
print ("Successfully sent email")
except smtplib.SMTPException:
print ("Error: unable to send email")
I have tried to add as destination email my #gmail.com email address too but I don't get anything.
I can see that the email is sent to the SMTP server but I don't get the email back:
---------- MESSAGE FOLLOWS ----------
b'From: From Person <from#mydomain.com>'
b'To: To Person <to#mydomain.com>'
b'Subject: SMTP e-mail test'
b'X-Peer: 127.0.0.1'
b''
b'This is a test e-mail message.'
------------ END MESSAGE ------------
Any idea on what am I doing wrong?
Generally, email is sent on the internet from email clients connecting to mail transfer agents (MTAs) that relay emails to mail delivery agents (MDAs) that store the email for the recipient to read. That is, GMail operates both as an MTA for its users, relaying GMail users' emails to remote mail servers, and as an MDA that receives emails slated for delivery to its users' mailboxes. Emails are transferred between servers using the SMTP protocol, and aiosmtpd is an implementation of the server-end of the SMTP protocol, whereas the built-in smtplib module is an implementation of the client-end.
When you run aiosmtpd in its default configuration, it is simply a dumb SMTP server that receives emails and spits them out on the terminal without relaying them or storing them. That is to say, aiosmtpd by itself is not an MTA or an MDA, unless you write code that implements storage of email (e.g. using the 'mailbox' built-in module), or you write code that implements relaying of email.
When you use the SMTP client smtplib.SMTP() to connect to 127.0.0.1, you are simply connecting to aiosmtpd, which won't do anything interesting with the email that you give it (unless you add code that does something interesting).
If you want to send email to remote email providers, e.g. GMail, then you need to either submit the email to a fixed MTA, or you need to implement the relaying mechanism yourself using DNS lookups.
If all you need is a simple MTA to relay email to remote hosts, then you don't need aiosmtpd or any other kind of Python programming - postfix is an excellent choice. Further reading: aiosmtpd is not an MTA
If you want to implement the relaying mechanism yourself, then you need to look up the MX record for the recipient's address (e.g. gmail.com) and then instruct smtplib.SMTP to connect to the host specified in the MX record. However, I wouldn't recommend trying to do this, as there are many pitfalls and cases to consider. For example - what to do if there are multiple MX records or no MX records at all. Furthermore, the remote SMTP server might not respond, or it may respond with a 4xx or 5xx error code, in which case you need to take appropriate action and retry at a later time.
Related
I'm php programmer and with php you can send email with server directly, for example this code send email to client:
<?php
$to = 'nobody#example.com';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: webmaster#example.com' . "\r\n" .
'Reply-To: webmaster#example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
?>
but in python you have to use smtplib and gmail or hotmail servers for sending email.
I wonder is there anyway to send email with python direct from server?
Other Options
When you use the mail functionality in PHP it is using the local sendmail of the host you are on, which in turn is simply a SMTP relay locally, of course locally sending emails is not really suggested as these are likely not have a good delivery rate due to DKIM, SPF and other protection mechanisms. If you care about deliverability I would recommend using either
An external SMTP server to send mail via which is correctly configured for the sending domain.
An API such as AWS SES, Mailgun, or equivalent.
If you do not care about deliverability then you can of course use local SendMail from Python, SendMail listens on the loopback address (127.0.0.1) on port 25 just like any other SMTP server, so you may use smtplib to send via SendMail without needing to use an external SMTP server.
Sending Email via Local SMTP
If you have a local SMTP server such as SendMail check it is listening as expected...
netstat -tuna
You should see it listening on the loopback address on port 25.
If it's listening then you should be able to do something like this from Python to send an email.
import smtplib
sender = 'no_reply#mydomain.com'
receivers = ['person#otherdomain.com']
message = """From: No Reply <no_reply#mydomain.com>
To: Person <person#otherdomain.com>
Subject: Test Email
This is a test e-mail message.
"""
try:
smtp_obj = smtplib.SMTP('localhost')
smtp_obj.sendmail(sender, receivers, message)
print("Successfully sent email")
except smtplib.SMTPException:
print("Error: unable to send email")
How can I avoid violating Gmail's terms of use when using Python's smtplib?
I would like to send internal emails using Python. After 2 days of fighting with the Gmail API, I gave up. Then I found the smtplib module, which looked simple and promising.
Following the example here, I wrote this small block of Python code:
import smtplib
# Details of where to send FROM
emailUser = 'an.account.I.made.just.for this.test#gmail.com'
emailPassword = 'password123'
# Send the following message to an address...
message = '[ I am email content ]'
toAddress = 'test.victim#gmail.com'
# Define the HEADER (to, from, and subject)
header = """
To: %s
From: %s
Subject: Python SMTPLIB Test
"""
header = header % (toAddress, emailUser)
# [ Don't know what this does ]
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
# Use User/Password credentials to send email
smtpserver.login(emailUser, emailPassword)
smtpserver.sendmail(emailUser, toAddress, message)
smtpserver.close()
I executed this script. It looks like Google's algorithms must have interpreted this as having been sent with bad intentions, and promptly closed my account! Which is fair enough, as I'm sure smtplib can be abused quite readily. However, I have honest intentions, but I do not know how to get around this issue: how can I avoid violating Gmail's terms of use when using Python's smtplib?
It could be because you are indiscriminately making connections with EHLO, you should be using HELO.
If the server supports EHLO, the client can use EHLO instead of HELO as its first request.
On the other hand, if the server does not support EHLO, and the client sends EHLO, the server will reject EHLO. The client then has to fall back to HELO.
There are a few servers that disconnect when they see EHLO. If the client finds that neither EHLO nor HELO was accepted, for example because the connection was closed, then it has to make a new connection and start with HELO.
I'm writing a program to help the school's Biology Department and it involves sending an email. I've gathered all of the variables I need for the content of the message, it's just the actual sending of the email that's causing some issues.
I've looked around and realized that I was using code that sent to gmail, whereas the servers at school use Outlook 2010. Once I remembered that, I looked around for some python code that sent emails, but so far nothing has worked.
It all seems very complicated for just sending an email, but I need some help as to were to go from here.
gsal.org.uk is our school's web server address, which is an outlook server.
The current error that I am receiving is smtplib.SMTPException: STARTTLS extension not supported by server., but I keep receiving various errors with everything I try.
This is the code:
fromaddr = "test#gsal.org.uk"
toaddrs = "technicians#gsal.org.uk"
msg = "\r\n".join([
"From: user",
"To: user",
"Subject: Practical Request",
"",
"Test"
])
server = smtplib.SMTP_SSL('smtp.gmail.com:465')
server.ehlo()
server.starttls()
# server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
messagebox.showinfo("Success!", "Your request has been sent successfully.")
All I want to do is send an email from an email account (specified within the program) to an email account that will soon be set up at school called technicians#gsal.org.uk. Any help appreciated.
EDIT
Thought I'd add the fact that if I remove the starttls() line, I get this:
smtplib.SMTPSenderRefused: (530, b'5.5.1 Authentication Required. Learn more at\n5.5.1 https://support.google.com/mail/answer/14257 hw1sm42144009wjb.6 - gsmtp', 'test#gsal.org.uk')
I've read that link, but it seems to be talking about gmail? I want to use outlook? I understand that I need to do authentication, but how?
In order to fight spam and protect resources, a normally configured SMTP server provides its services only to its owner (e.g. a company, organization or registered customers). Your school server probably accepts mail only if it is:
addressed to the school's own domain, or
coming from an authenticated person (e.g. a student, teacher), or
coming from a host with IP address belonging to the school's LAN (when allowed by the admin)
Further, a SMTP server communicates with other servers on TCP port 25 and with users submitting new mail (which is your case) on port 465 or 587. (Port 25 was used in the past for all mail, this is now deprecated)
Communication on port 465 is always encrypted (TLS). Communication on port 587 starts in plaintext, but with the STARTTLS command, the encryption is turned on. A successfull STARTTLS is usually required to allow authentication (login).
Why your progam does not work?
You are trying to start TLS on an TLS connection. It has been started. Either don't STARTTLS or change the port to 587.
You are using gmail's server to send a message not addressed to gmail. In this case you must login with a name and a password as a registered gmail user.
What should help? Contact the local admin for details about using the school's own server.
I'm using smtplib to send email via AOL account, but after successful authentication it gets rejected with following error.
reply: '521 5.2.1 : AOL will not accept delivery of this message.\r\n'
reply: retcode (521); Msg: 5.2.1 : AOL will not accept delivery of this message.
data: (521, '5.2.1 : AOL will not accept delivery of this message.')
Here's explanation for this error.
The SMTP reply code 521 indicates an Internet mail host DOES NOT ACCEPT
incoming mail. If you are receiving this error it indicates a configuration
error on the part of the recipient organisation, i.e. inbound e-mail traffic
is being routed through a mail server which has been explicitly configured
(intentionally or not) to NOT ACCEPT incoming e-mail.
Recipient mail (in my script) is valid (gmail) address and after this debug message mail gets rejected.
send: 'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nSubject: My reports\r\nFrom: myAOLmail#aol.com\r\nTo: reportmail#gmail.com\r\n\r\nDo you have my reports?\r\n.\r\n'
Here's short version of code:
r_mail = MIMEText('Do you have my reports?')
r_mail['Subject'] = 'My reports'
r_mail['From'] = e_mail
r_mail['To'] = 'reportmail#gmail.com'
mail = smtplib.SMTP("smtp.aol.com", 587)
mail.set_debuglevel(True)
mail.ehlo()
mail.starttls()
mail.login(e_mail, password)
mail.sendmail(e_mail, ['reportmail#gmail.com'] , r_mail.as_string())
Is this some kind of permission problem because I'm successfully sending same email with Yahoo account without any problems?
I guess that AOL doesn't allow relay access by default or you have not configured it manually. The error you get says that aol doesn't have recipient you want to send message. In this case if you want to send email to gmail account try to connect to gmail SMPT server instead of AOL.
Change smpt server to gmail-smtp-in.l.google.com for example and turn off authentication.
Was running into 5.2.1 : AOL will not accept delivery of this message. from the AOL SMTP relay myself. What I ended up needing was valid From and To headers in the MIME message body, as opposed to just the SMTP connection.
In your particular case there could be any number of reasons for getting this 5.2.1 bounce. The postmaster.aol.com site has some helpful tools to diagnose, as well as some pretty vague documentation for this specific error message. In my case I ended up packet sniffing the SMTP messages that my Thunderbird email client was sending vs. the Python script, and eventually spotted the difference.
postmaster.aol.com documentation:
https://postmaster.aol.com/error-codes
AOL will not accept delivery of this message
This is a permanent bounce due to:
RFC2822 From domain does not match the rDNS of sending server.
RFC 2822 FROM address does not have an A record and is not a valid domain.
IP has a poor reputation and mail is sent to multiple recipients.
There are multiple From address in the mail headers and the IP reputation is poor.
My Python function for sending mail through smtp.aol.com:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def genEmail(user, passwd, to, subject, message):
smtp=smtplib.SMTP_SSL('smtp.aol.com',465)
smtp.login(user, passwd)
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = user # This has to exist, and can't be forged
msg['To'] = to
msg.attach(MIMEText(message, 'plain'))
smtp.sendmail(user, to, msg.as_string())
smtp.quit()
I've tried playing around in python to learn more about the smtp protocol. More precisely I'm been trying to send a mail straight to a host's smtp server, but with little success.
For example, say I want to send a mail to a gmail.com address, I lookup the mx record for gmail.com:
>> nslookup -type=MX gmail.com
gmail.com MX preference = 40, mail exchanger = alt4.gmail-smtp-in.l.google.com
gmail.com MX preference = 5, mail exchanger = gmail-smtp-in.l.google.com
gmail.com MX preference = 10, mail exchanger = alt1.gmail-smtp-in.l.google.com
Then I do the following in python:
import smtplib
# Tried both port 465 and 587 (can't test port 25 since it's blocked by my ISP)
s = smtplib.SMTP("alt1.gmail-smtp-in.l.google.com", 587)
I tried several, and for everyone but one I always got a:
"[Errno 10051] A socket operation was attempted to an unreachable network" or
"[Errno 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because conneted host has failed to respond" exception.
I read somewhere that some mail servers do a reverse lookup on your IP, and rejecting the connection if it hasn't got a domain. How do they do that?
I also read somewhere that many mail servers reject incoming mails from dynamic IP addresses (which I obviously have as a private customer to my ISP). How can they check if an IP address is dynamic or static?
Are these the reasons most servers seem to reject my connection? Or is there something more to it?
Um, your problem is exactly this:
# Tried both port 465 and 587 (can't test port 25 since it's blocked by my ISP)
Google's MX server is listening on port 25. If your ISP does not allow outgoing connections on this port, then you will not be able to send SMTP messages the way you are trying to do. You should get this sorted out with your ISP.
Regarding the rejection of messages, sending e-mail directly like this does increase the likelihood that it will be rejected or flagged as spam. Particularly if you set the "from" address to something that does not match the domain associated with your IP address, or if your SMTP client sends a mismatched domain in its EHLO message, or if the content of your message looks "spammy". The actual behavior will vary according to how each individual MX server has been configured.
Direct to MX email like you describe above will be blocked by Gmail's SMTP servers, with an error message "421-4.7.0", however many other SMTP severs, like MailEnable will allow Direct To MX.
The following website has source code for .NET and PHP for Direct to MX code, http://www.directtomx.com - you may be able to consume the webservice in python using SUDS.