how to find the smtp server of an email address python - python

so i have an email address like: example#unknowndomain.com
i want to check what is the smtp host that this email is connected to
is there any way i can do this in python?
at the end i want to check if smtp host of the email matches a certain host i have like:
email = example#unknowndomain.com
smtp_host = smtp.smtphost.com
email_smtp_host =smtp.emailsmtphost.com
if email_smtp_host == smtp_host:
True
else:
False
i tried looking through the smtplib but couldn't find anything useful

This is not something you can simply get by code. The SMTP server is the outgoing mail server and this depends on the email provider. There is no standard in this, and these are not exposed like the MX records for incoming email.
You might be able to find a list of SMTP servers such as this one but you would still need to know who the email provider is. You might be able to figure this out by looking at the MX records for the domain, and then choose the SMTP server based on that.
Example:
Needs installation of the non-default dnspython module using pip install dnspython
import dns.resolver
domain = 'gmail.com'
for x in dns.resolver.resolve(domain, 'MX'):
print(x.to_text())
This should print out the MX records for the domain gmail.com, which you would then have to check against some database containing the SMTP servers for all the email providers (linked to their MX records)
As I stated, this is not something that can be done easily and would require quite a bit of groundwork/legwork...

Related

Check Email is exist on SMTP server in Python?

I created a script for validating Email is really exists on SMTP server all are working Fine but some fake email also send response 250 OK. how can I manage this issue. please help me.
try:
domain_name = addressToVerify['Email'].split('#')[1]
records = dns.resolver.query(domain_name, 'MX')
mxRecord = records[0].exchange
mxRecord = str(mxRecord)
host = socket.gethostname()
server = smtplib.SMTP()
server.set_debuglevel(0)
server.connect(mxRecord)
server.helo(host)
server.mail('example#example.com')
code, message = server.rcpt(str(addressToVerify['Email']))
server.quit()
First of all, email address verification is a feature that was "banned" (ok, right, it is still there, but hardly one enables it in production scenarios) from the email related RFCs, because of obvious reasons: it become something it was never intended for, heaven for spammers. However, it could work only for local accounts. Because this is how email delivery works. The SMTP part of the concept is only for sending, for delivery. It is a relay. The SMTP server has no idea of the addressees because it is only trying to pass the message to the next hop - which can, of course, be the local server, but can as well be any remote one. It is using the DNS MX records to get the other SMTP party's address from the email addresses domain part. If found, it connects to the other server and passes the message. If it is a local one, it contacts the local delivery agent that manages the actual mailboxes. That one will know if the mailbox exists or not. If not, it will react based on its configuration: it might or might not replay with any warning. But all this happens asynchronously, because of the nature of the internet.
However, as you can see, the SMTP server itself is either way unable to tell if the addressee mailbox actually exists - except for local addresses. You can verify MX record yourself, but that is telling you if there is an SMTP server registered to that email domain or not - and check for its availability on the network. Nothing more. But you can practically not expect VRFY to work.
Sidenote: the local agent is not directly bound to any the mailbox protocol. You can have a mailbox without a mailbox protocol server running. It makes little sense, but it is not technically required.
Of course, most email services you can get for any operating system will be complex ones housing SMTP, delivery agent and a POP3 or IMAP/MAPI server.

Why separate authentication is required for imap and smtp?

I am using imaplib and smtplib libraries of python
However I have to separately login to imap and smtp servers like below
imap:
self.imap = imaplib.IMAP4_SSL(self.imap_server,self.imap_port)
r, d = self.imap.login(self.username, self.password)
smtp:
self.smtp = smtplib.SMTP(self.smtp_server, self.smtp_port)
self.smtp.ehlo()
self.smtp.starttls()
self.smtp.login(self.username, self.password)
Is there be any method which can login to both at a same time?
The root cause here is that neither the IMAP protocol nor the SMTP protocol offer a way to say "you can use the same credentials here as for (some other service)" or anything like that. Such a protocol feature would be possible, perhaps as a SASL feature, but it's not a simple extension.
It wasn't done in the bronze age because SMTP only started using passwords when spammers and mobile devices came along. Until then, IMAP used passwords but SMTP generally not.
So we're left with lots of people assuming that the two are the same, lots of clients supporting only that case, but the client libraries work as if IMAP and SMTP were different worlds.

use different outgoing port for smtp server

While setting-up smtp server using smtplib on Python, you get the option to specify hostname and port. But those correspond to the remote host I am sending mail to. And there are other similar questions for this.
I want to change the underlying port, that smtplib will use to send the mail.
I want to change it from 25 to something else as the Google Cloud Platform instance I am using has blocked 25.
Please don't suggest using third party services like sendgrid.
And also I didn't find these answers useful
1
2

Testing python smtp email service

So I wrote a simple email service using smtplib to send welcome emails when user first logs in. I was wondering what's the best way to test out my code.
def send_email(nickname, email):
msg = MIMEMultipart('alternative')
config = read_config_file(MAIL_CONFIG_PATH)
sen = config.get('gmail_credentials', 'email')
pwd = config.get('gmail_credentials', 'password')
server = None
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(sen, pwd)
server.sendmail(sen, [email], msg.as_string())
return 'Sent!'
finally:
if server:
server.quit()
I found out that you can use a fake smtp server:
sudo python -m smtpd -n -c DebuggingServer localhost:25
But I am still not sure how I should implement something like this into my code. How do I change my API so that it runs the SMTP server during testing and connects to the GMAIL server for the actual calls? And are there init scripts which will run the SMTP server on our servers (this will be deployed on AWS EC2).
To anyone who comes across this old ticket with the same issue, I wanted to write integration tests with the standard library, so the above solutions didn't work for me. Setting up a debugging server locally within the unit testing code was also a bit tricky, and allegedly doesn't support starttls. In the end I went with this;
import smtplib
from unittest import TestCase
class TestSMTP(TestCase)
...
setup etc.
def test_smtp_connection(self):
# connect to actual host on actual port
smtp = smtp.SMTP(host, port)
smtp.starttls()
# check we have an open socket
self.assertIsNotNone(smtp.sock)
# run a no-operation, which is basically a server-side pass-through
self.assertEqual(smtp.noop(), (250, '2.0.0 OK'))
# assert disconnected
self.assertEqual(smtp.quit(), (221, '2.0.0 Service closing transmission channel'))
self.assertIsNone(smtp.sock)
Note, these are integration tests, which is all you need to do to verify your email server is working. Everything else can be done by mocking smtp.SMTP and capturing whatever's passed into sendmail and verifying the contents there. You're not unit testing smtp, you're unit testing your application.
Disclaimer: I worked on the product in question, please note this answer may contain bias.
I co-founded a hosted service called Mailosaur, that allows developers (us included) to test this kind of process in a real-world setting (i.e. over the net, using SMTP).
You get an SMTP endpoint (also unlimited test email addresses, but you're using SMTP so shouldn't need this).
The service then converts emails into a JSON representation, which you can get via an HTTP API.
To make the querying a little easier use can use client bindings (available for Java, .NET and Ruby), but you can use regular curl or any other HTTP client (or get in touch and we'd be happy to put together a Python client).
The final test process would be:-
Send email via SMTP to smtp.mailosaur.in (no need to change to from/to addresses)
Query the API:
curl https://mailosaur.com/v2/emails?mailbox={mailbox}&key={api_key}
Do your regular asserts (pseudo code):
assert.equal(3, email.attachments.length, 'Expected 3 attachments');
assert.contains('https://verify-url', email.html.links, 'Expected link to verification url');
I had the same problem: applications that send email, and I want to check that they do so correctly without spamming a bunch of real people with email of various forms of incompletenese.
I use PostHoc which receives email using SMTP, but then simply displays the email that was sent in a web browser.
It is on GitHub at: https://github.com/agilepro/posthoc
Here is a blog post that describes it: https://agiletribe.purplehillsbooks.com/2017/07/24/posthoc-testing-apps-that-send-email/
The reason I don't run a real SMTP server is that those servers are designed to actually find the and deliver the mail to the recipients. I want to test the application with real email address and real mailing lists. I want to see that the real situation can be handled, and I want to verify that each email sent looks the way it should. I want all this, but I want to be sure that no email is ever actually delivered.
For years I had a switch in the application that redirected email to a different address, and I could see the email there. But this is still problematic since the application is running in a different mode than it will in production. With PostHoc the application runs exactly as it will in production, and I still can safely see all the email sent.
PostHoc requires TomCat to run it, but nothing else.
I like the way it automatically deletes all the old messages after 5 days. I have never needed to see one of these emails after 5 days, and so I just never need to do any clean up around it.

Start local SMTP server

I'm going to transfer crash dumps from clients to me through the mail mechanism. Therefore, I can't use any public SMTP servers, as packing any account's credentials with the application is unacceptable.
Therefore, I need to send mails through my application directly to the destination mail server.
How can I achieve this in python? (I'm using windows so sendmail is not an option)
Just use smtplib in the standard library.
Trying to write code that can send mail to anyone is problematic, because smtplib connects to servers client-to-server style rather than server-to-server-relay style.
But if you only need to send mail to one particular server, which you control, it's trivial. Just configure your server at 'mail.example.com' to accept any mail from 'crash-reports#example.com' to 'crash-reports#example.com'.
Your code will look something like this:
import smtplib
addr = 'crash-reports#example.com'
def send_crash_report(crash_report):
msg = ('From: {}\r\nTo: {}\r\n\r\n{}'.format(
addr, addr, crash_report)
server = smtplib.SMTP('mail.example.com')
server.sendmail(addr, [addr], msg)
server.quit()
As a side note, if you're just starting on a crash report collector, you may want to consider using a web service instead of a mail address. You're going to run into problems with people who can't access port 25 through their corporate firewall/proxy, write code that extracts the crash reports from an inbox (and/or searches via IMAP or mbox or whatever), deal with spammers who somehow find crash-reports#example.com and flood it with 900 messages about Cialis for each actual crash report, etc.

Categories

Resources