I need to check emails programmatically. I'm using this code:
resolver = dns.resolver.Resolver()
resolver.timeout = 3
resolver.lifetime = 3
mx_records = resolver.query(domain, 'MX')
for mxRecord in mx_records:
mxRecord = str(mxRecord.exchange)
host = socket.gethostname()
server = smtplib.SMTP(timeout=30)
server.set_debuglevel(0)
addressToVerify = var0
server.connect(mxRecord)
server.helo(host)
server.mail('me#domain.com')
code, message = server.rcpt(str(addressToVerify))
server.quit()
res_email = 'Not Found'
if code == 250:
result = 'Success'
else:
print "doesn't exist"
I'm receiving an error when I run this code:
Connection unexpectedly closed
Connection unexpectedly closed: [Errno 10054]
[Errno 10061]
I have tried to change values of timeout, but it didn't help. I then tried to specify the port in smtplib.SMTP(), but specified 587 and that didn't resolve the issue either.
How can I solve this problem?
You can copy the code to interrogate a POP3 server from the Python help file. Here it is in ever-so-slightly modified form.
import poplib, getpass
pop = poplib.POP3('***********', port=110)
pop.user('**********')
pop.pass_('*********')
print (pop.stat())
print (pop.list()[1])
You have only to copy various constants such as the port number from your mail client.
What this script produces as output might surprise you, depending on the settings in your mail client. Here's what I just got.
(43, 1104784)
[b'1 15848', b'2 7889', b'3 7938', b'4 3705', b'5 28933', b'6 35479', b'7 12793', b'8 7094', b'9 10045', b'10 12793', b'11 17194', b'12 312802', b'13 12688', b'14 18431', b'15 24454', b'16 17769', b'17 16223', b'18 14975', b'19 11951', b'20 13373', b'21 34949', b'22 23647', b'23 14958', b'24 22449', b'25 5068', b'26 14920', b'27 8611', b'28 10982', b'29 14311', b'30 7477', b'31 3852', b'32 8497', b'33 4086', b'34 7240', b'35 69458', b'36 19430', b'37 110263', b'38 2434', b'39 12043', b'40 5306', b'41 10288', b'42 17164', b'43 74974']
But I know that no messages remain on the server that I haven't received in my mail client. The answer to this minor puzzle is that my email client leaves messages on the server for a fortnight, or until I delete them, by default, presumably as a safeguard against loss in case of some kind of computer failure.
This implies that it would be insufficient to simply use the above output as a check for new messages. It would be necessary to record dates from headers from received messages for up to a fortnight for comparison with those on the server.
Related
I'm writing this currently for an assignment but years back I had the same problem and just gave up. Further searches had me try a variety of things and I cannot get past the login portion.
from socket import *
from ssl import *
msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"
clientSocket = socket(AF_INET, SOCK_STREAM)
mailserver = getaddrinfo('smtp.gmail.com',465, AF_INET, SOCK_STREAM, IPPROTO_TCP)[0][4]
clientSocket = wrap_socket(clientSocket)
clientSocket.connect(mailserver)
recv = clientSocket.recv(1024)
print recv
if recv[:3] != '220':
print '220 reply not received from server.'
clientSocket.send('EHLO Nolan\r\n')
recv = clientSocket.recv(1024)
print recv
if recv1[:3] != '250':
print '250 reply not received from server.'
clientSocket.send('AUTH LOGIN ' + 'my Google email'.encode('base64','strict'))
recv = clientSocket.recv(1024)
print recv
print recv.split()[1].decode('base64')
clientSocket.send("my password".encode('base64','strict'))
recv = clientSocket.recv(1024)
print recv
# And onto other tasks
I'm under the impression I don't need STARTTLS as I start the connection with SSL. If I change AUTH LOGIN to AUTH PLAIN it doesn't know how to decode it. If I use PLAIN but don't encode it my program just hangs. If I terminate it with "\n\r" (not encoded) I get a broken pipe. Using the code above I get the password request.
Then sending the password I get 535-5.7.8 Username and Password not excepted.It's the same password I sign in with?!? I already setup my account to allow less secure devices. 2-step verification... started the process seems to be orientated to mobile phones, not my python app.
I've changed EHLO to use my IP, as I believe RFC 5321 says that's how it should be. Didn't matter.
I've looked through RFC 4954...
I dug into smtplib to uncover "AUTH PLAIN " + encode_base64("\0%s\0%s" % (user,pass),eol='') Just hangs... waiting...
I have no clue.
Update
I changed the smtplib to output every string submitted. This confuses me even more:
ehlo [127.0.1.1]
AUTH PLAIN [almost forgot one can decode this base64]==
mail FROM:<[gmail account]>
rcpt TO:<[hotmail account]>
data
quit
My AUTH string is exactly the same but it hangs. And I am receiving the email at my hotmail account (using smtplib, not my code).
If you want a basic, non-SSL connection to Gmail, you can use this:
import smtplib
gmail = smtplib.SMTP("smtp.gmail.com",587)
gmail.ehlo() #open the connection
gmail.starttls()
gmail.login("gmaillogin","gmailpassword") #login*
gmail.quit() #close the connection
*Note: You will need to generate a gmail application password from your google account.
Edit:
If you want to use SSL encryption, use this (thanks to furas):
import smtplib
gmail = smtp.SMTP_SSL("smtp.gmail.com",465)
gmail.ehlo()
gmail.login("gmaillogin","gmailpassword")
gmail.quit()
As is typically my fashion, it's the simple things. I just spent hours looking over one program and Googling only to have one error pop out at me: the parameter order in my definition was not how I used it in my code.
Here... I changed my code to use AUTH PLAIN and the issue... I had been putting in '\n\r' not '\r\n' (if I had ended the command with anything, only omitted because '\n\r' produced errors on some commands and went through okay on others). Thank you for classical music to study by on your favorite streaming video site. It raised my intelligence briefly. :)
clientSocket.send('AUTH PLAIN ' + encode_base64("\0%s\0%s" % ([email],[password]), eol="") + '\r\n')
i've a python script, run on a raspeberry pi that monitoring my server room and periodically send me an e-mail and make other stuff.
First time script is running it send a notification and works fine, then wait for a time (5 or 30 minutues) depending if an alarm is triggered, so i've write a for loop to wait. when the loop is finish, script make a call of the function for sending e-mail and python return an error.
Could someone help me ?
i test it also on debian 7.7.0 box and i've the same error.
Below a sample script and the error.
Thanks in advance.
Dom.
File "/usr/lib/python2.7/smtplib.py", line 361, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
# Import
from time import sleep
import time
import smtplib
import sys
import string
smtp_server = "10.0.0.4" # mail server address
mail_from = "server#domain.com"
mail_to = "user#gmail.com"
mail_subj = "Server room notify"
server = smtplib.SMTP(smtp_server)
valore = 24 # value for the funtion
def SendAlertEmail(t_value):
log_t = time.strftime("%d/%m/%A %H:%M:%S ")
Text = string.join("Server room notify \n " + str(log_t) + str(t_value))
Body_email = string.join((
"From: %s" % mail_from,
"To: %s" % mail_to,
"Subject: %s" % mail_subj,
"",
Text
), "\r\n")
server.sendmail(mail_from,mail_to,Body_email)
return
SendAlertEmail(valore) # calling from here works fine
for i in range(0,500):
sleep(1)
print(str(i))
SendAlertEmail(valore) # after 500 secs goes in error. Test on debian 7.7.0 python 2.7.3 gcc 4.7.2
smtplib opens a TCP connection at the creation of the SMTP object. You try to reuse it after 500 seconds of inactivity when it is likely that a timeout has already closed the connection.
You should keep only the server name, an create a new SMTP object for each connection in your use case, because the delay between sending messages is too high.
As Serge Ballesta mentions, you should open and close the connection to the server for each one the sent e-mails.
Some months ago I programmed a class to send e-mails in Python, which you can find here: https://github.com/kmundnic/Habitus/blob/master/data_sender.py You create a DataSender object and it handles the connections to the server. Also, it calls a JSON file where the accounts and password is stored, so you don't save it in your code.
Feel free to use it. It was adapted from http://kutuma.blogspot.com/2007/08/sending-emails-via-gmail-with-python.html, as it's mentioned in the comments at the beginning of the source code.
I have been trying to verify an email address entered by the user in my program. The code I currently have is:
server = smtplib.SMTP()
server.connect()
server.set_debuglevel(True)
try:
server.verify(email)
except Exception:
return False
finally:
server.quit()
However when I run it I get:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
So what I am asking is how do i verify an email address using the smtp module? I want to check whether the email address actually exists.
Here's a simple way to verify emails. This is minimally modified code from this link. The first part will check if the email address is well-formed, the second part will ping the SMTP server with that address and see if it gets a success code (250) back or not. That being said, this isn't failsafe -- depending how this is set up sometimes every email will be returned as valid. So you should still send a verification email.
email_address = 'example#example.com'
#Step 1: Check email
#Check using Regex that an email meets minimum requirements, throw an error if not
addressToVerify = email_address
match = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', addressToVerify)
if match == None:
print('Bad Syntax in ' + addressToVerify)
raise ValueError('Bad Syntax')
#Step 2: Getting MX record
#Pull domain name from email address
domain_name = email_address.split('#')[1]
#get the MX record for the domain
records = dns.resolver.query(domain_name, 'MX')
mxRecord = records[0].exchange
mxRecord = str(mxRecord)
#Step 3: ping email server
#check if the email address exists
# Get local server hostname
host = socket.gethostname()
# SMTP lib setup (use debug level for full output)
server = smtplib.SMTP()
server.set_debuglevel(0)
# SMTP Conversation
server.connect(mxRecord)
server.helo(host)
server.mail('me#domain.com')
code, message = server.rcpt(str(addressToVerify))
server.quit()
# Assume 250 as Success
if code == 250:
print('Y')
else:
print('N')
The server name isn't defined properly along with the port. Depending on how you have your SMTP server you might need to use the login function.
server = smtplib.SMTP(str(SERVER), int(SMTP_PORT))
server.connect()
server.set_debuglevel(True)
try:
server.verify(email)
except Exception:
return False
finally:
server.quit()
you need to specify the smtp host (server) in the SMTP construct. This depends on the email domain. eg for a gmail address you would need something like gmail-smtp-in.l.google.com.
The server.verify which is a SMTP VRFY probably isnt what you want though. Most servers disable it.
You might want to look at a service like Real Email which has guide for python. How to Validate Email Address in python.
Absolute newbie here, and I can't quite seem to find the answer to my question. Running python 2.7.
My code for the server is as follows:
#UDPPingerClient.py
from socket import *
#Create a UDP socket
clientSocket = socket(AF_INET, SOCK_DGRAM)
#Assign IP address and port number to socket
clientSocket.bind(("127.0.0.1",9501))
#Set a timeout value of 1 second
clientSocket.settimeout(1)
msg = "test"
#the server info
sIP = "127.0.0.1"
sPort = 12007
addr = (sIP,sPort)
a = 10
# the server will automatically drop some messages
# so we send 10 to make sure it gets there and then
# listen for a response from the server
while a > 0:
clientSocket.sendto(msg,addr)
try:
received, server = clientSocket.recvfrom(1024)
print received
except timeout:
print ('an error occured')
a = a - 1
The server code:
# UDPPingerServer.py
# We will need the following module to generate randomized lost packets
import random
from socket import *
# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(("127.0.0.1", 12007))
while True:
# Generate random number in the range of 0 to 10
rand = random.randint(0, 10)
# Receive the client packet along with the address it is coming from
message, address = serverSocket.recvfrom(1024)
# Capitalize the message from the client
message = message.upper()
12 # If rand is less is than 4, we consider the packet lost and do not respond
if rand < 4:
continue
# Otherwise, the server responds
serverSocket.sendto(message, address)
Thus far I haven't been able to get a reply from the server. The most I've been able to accomplish is sending once and timing out before getting this error:
an error occured <-- output from exception
Traceback (most recent call last):
File "C:/Python27/UDPPingerClient.py", line 23, in <module>
received, server = clientSocket.recvfrom(1024)
error: [Errno 10054] An existing connection was forcibly closed by the remote host
The reproducibility on this one is 100%, this is the outcome every time I run the server file and then the client file. Same thing with the firewall on or off. I have a feeling this has to do with the exception but I can't quite wrap my head around why.
this is the output i got:
foggy#dew ~ $ python UDPPingerClient.py
TEST
TEST
an error occured
TEST
TEST
TEST
an error occured
TEST
an error occured
TEST
exactly ten messages, some have timeouted others were passed back.
besides that extra 12 above rand line in Server (and that doesn't bother the interpreter) i don't see anything wrong with the code.
I'm building a game-server in Python. The functionality is pretty well-defined. The server will listen on the port 6000 and a remote client will send a request. Then the server will establish a connection to the client's port 7000. From then on, the client will keep sending 'requests' (basically, strings such as "UP#", "DOWN#", "SHOOT#" etc.) to server's port 6000.
This is the problem. I have made a 'server' who listens on the port 6000. This means I cannot bind a client to the same port. Is there a way that I can get the data string of an incoming request in a server? So far, I only have this.
What am I doing wrong here? Any workarounds for this issue? In short, can I read the incoming request string from a client in the server code?
Thanks in advance.
def receive_data(self):
errorOccured = False
connection = None
try:
listener = socket.socket() # Create a socket object.
host = socket.gethostname()
port = 6000 # The port that the server keeps listening to.
listener.bind(('', port))
# Start listening
listener.listen(5)
statement = ("I:P0:7,6;8,1;0,4;3,8;3,2;1,6:5,4;9,3;8,7;2,6;1,4;2,7;6,1;6,3:2,1;8,3;5,8;9,8;7,2;0,3;9,4;4,8;7,1;6,8#\n","S:P0;0,0;0#","G:P0;0,0;0;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#", "C:0,5:51224:824#","G:P0;0,0;0;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#","G:P0;0,1;2;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#")
# This is just game specific test data
while True:
c, sockadd = listener.accept() # Establish connection with client.
print 'incoming connection, established with ', sockadd
i = 0 # Just a counter.
while i<len(statement):
try:
self.write_data(statement[i], sockadd[0])
time.sleep(1) # The game sends updates every second to the clients
i = i + 1
#print listener.recv(1024) -- this line doesn't work. gives an error
except:
print "Error binding client"
c.close() # Close the connection
return
except:
print "Error Occurred"
I'm going to answer it because I got some help and figured it out.
The most basic thing I can do is to use the client connection which is c for this purpose. In here, instead of the commented line data=listener.recv(1024) I should have used data= c.recv(1024). Now it works.
Another way is to use SocketServers with a StreamingRequestHandler. While this is ideal for usage of typical servers, if a lot of objects are involved it could reduce the flexibility.