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.
Related
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.
So I tried to send E-Mails via Python from on of my E-Mail Accounts to another, and no matter what i try, i get different Error messages, and googling them won't help me. All suggested fixes don't work for me and im just exhausted. I tried it on GMail and on web.de, both doesnt work.
Error messages (depend on encrpyption (tls/ssl) or provider (web.de/gmail)):
Username and Password not accepted.
Transaction failed Unauthorized sender address.
SSL: WRONG_VERSION_NUMBER
My Code in a nutshell:
context = ssl.create_default_context()
with smtplib.SMTP_SSL('smtp.web.de', port, context=context) as server:
server.login(sender, password)
server.sendmail(sender, reciever, message)
Try to set the correct ssl.SSLContext for your server.
For example:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
or
context = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
https://docs.python.org/3.0/library/ssl.html
with smtplib.SMTP_SSL('smtp.web.de', port, context=context) as server:
It is unclear which port you are using but you like you the wrong one or you should not use smtplib.SMTP_SSL. SMTP_SSL is for connections where TLS is spoken from start (implicit TLS). This is true for port 465 (smtps).
smtp.web.de does not offer access with port 465 in the first place. This means that underlying TCP connection would already fail which would result in a different error.
Therefore it is likely that you've used port 25 (smtp) or port 587 (submission). Both of these ports require explicit TLS though, i.e. they start with a plain connection and upgrade to TLS only after an explicit STARTTLS command. For these ports the code should look something like this instead:
context = ssl.create_default_context()
port = 587
with smtplib.SMTP('smtp.web.de', port) as server:
server.starttls(context=context)
server.login(sender, password)
...
Connecting with implicit TLS to a port which does not use implicit TLS can result in very strange error messages since the TLS stack tries to interpret the response from the server as TLS even though it is not TLS (in this case the plain welcome message from the SMTP server, i.e. 220 ... Service ready). Thus the WRONG_VERSION_NUMBER you see does not actually indicate the wrong version of the response but only that it tried to interpret a specific part of the plain response as the TLS version number and got unexpected results from this.
I've been running an instance of Django on Windows R2 2012 for over a year and I've come to a road block. Yesterday something happened, I don't know what it could be. The same two errors keep popping up at different times though when trying to send an email:
[WinError 10060] A connection attempt failed because the connected
party did not properly respond after a period of time, or established
connection failed because connected host has failed to respond
and
socket.gaierror: [Errno 11001] getaddrinfo failed
Users are able to connect to the IP address of the server and the port Django is running on 192.168.1.5:8000, but they cannot send emails anymore. Though a percentage do go through as described here, but very few.
Things I've tried
1) This solution
import socket
socket.getaddrinfo('localhost', 8000)
Since I'm doing python manage.py runserver 192.168.1.5:8000, I added that IP and nothing.
2) I went into the Firewall settings and made sure that the ports were all good. The SMTP one that is declared in the setting.py file in my Django project and 25. All of them, inbound and out.
3) I tried sending things on my local machine and it does work. I used other programs that do not use Django to send emails and they do process on all other machines except the Server. So I know it's not my email server.
4) I changed the email config to use my Gmail account and it does process on all other machines except for the server. So it has to be the environment.
5) Editing http_proxy environment variables
The problem, in my case, was that some install at some point defined
an
environment variable http_proxy on my machine when I had no proxy.
Removing the http_proxy environment variable fixed the problem.
As described here
and in my Django project in the wsgi.y file:
os.environ['http_proxy'] = "http://192.168.1.5:8080"
os.environ['https_proxy'] = "http://192.168.1.5:8080"
6) Given this answer here (can someone please explain how I would do it to a django email function), I've also tried this method of wrapping it from solutions here
import smtplib
import socks
#socks.setdefaultproxy(TYPE, ADDR, PORT)
socks.setdefaultproxy(socks.SOCKS5, '192.168.1.5', 8080)
socks.wrapmodule(smtplib)
smtpserver = 'smtp.live.com'
AUTHREQUIRED = 1
smtpuser = 'example#hotmail.fr'
smtppass = 'mypassword'
RECIPIENTS = 'mailto#gmail.com'
SENDER = 'example#hotmail.fr'
mssg = "test message"
s = mssg
server = smtplib.SMTP(smtpserver,587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(smtpuser,smtppass)
server.set_debuglevel(1)
server.sendmail(SENDER, [RECIPIENTS], s)
server.quit()
Though I wouldn't like to use such a method as I'd prefer using Django's built in email service.
Since you have not changed the code and errors you shared shows that it's a network related problem.
It's most probably a DNS issue. In your settings.py you have specified the EMAIL_HOST, which is i believe a hostname. You need to check you server's DNS server.
You are mentioning about checking your firewall settings but what you are doing wrong is not checking the actual connection.
To address the problem you can use couple of command line utilities like telnet or nslookup. You can check if you can resolve a hostname:
nslookup smptp.mail_host.com
This command will fail most probably.
I would like to point what you did wrong in your steps:
1) You have tried to get your services getaddrinfo in which you needed to put your smtp servers hostname, which would result with the same error. Sockets are the very primitive part of the connection on the application layer, you don't really need to dig in to that.
2) Checking firewall settings is OK.
3) This is a good step which shows that there is a problem with your servers network connection.
4) That is another evidence :)
5) You have got it wrong, if you have a proxy server on your network to connect external networks, than you use this settings. But you have configured it wrong. You should not set your projects url as proxy server.
6) This is another deep level coding. You should not use such low level script, which will cause you numerious problems, which would have been handled in high level modules.
I focused my answer on the strange fact that you can get around the problem using a SOCKS5 proxy. (I believe you. There was no time to ask you for details.) You verified that your example solution by SOCKS5 works for you. Django uses the same smtplib and you can easily wrap it the same way by this code added to wsgi.py.
import smtplib
import socks # it is the package SocksiPy or PySocks
socks.setdefaultproxy(socks.SOCKS5, '192.168.1.5', 8080)
socks.wrapmodule(smtplib)
Http(s) proxy (paragraph 5)) is not related because it does not affect SMTP and other protocols except http(s) because "SOCKS operates at a lower level than HTTP proxying".
I am trying to send a message with python using the smtplib library.
Here is the code I am using:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(EMAIL, PASS)
server.sendmail(EMAIL, phone_number +"#"+ carrier_address, msg)
server.quit()
I am using the port 465 to use a secure connection when connecting, but this still gets the message blocked when sending to a tmobile phone number. It seems that any other carrier works.
Has anyone else run into this issue? My website depends on these texts, and they have to be on time, so this is a very bad bug.
Is there a workaround to this or any other library out there to make this work?
Assuming you are getting the 550 block message from T-Mobile, I found this discussion that goes over the problem. Ths gist is downwards, but here's the main quote:
Sender Policy Framework 550 status message is part of spam validation screening. "550" is part of a long list of SMTP status codes to help diagnose connection issues. Mail relays connecting to #tmomail.net DNS and MX (mail) records must match or be authorized on behalf of another domain. The mismatch can occur in the registered domain or the shared ISP network connection.
I don't know how to update DNS or MX records as I am just a humble pythoner trying to text some folks. If you worked through your error already, what worked for you? Thanks.
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.