python SMTP - socket error - python

I have a python script to run a SMTP server in localhost. This is my very simple code:
import smtpd
import asyncore
class CustomSMTPServer (smtpd.SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
print 'Receiving message from:', peer
print 'Message addressed from:', mailfrom
print 'Message addressed to :', rcpttos
print 'Message length :', len(data)
server = CustomSMTPServer(('127.0.0.1', 25), None)
asyncore.loop()
If I send an email from an email client running on localhost the email arrives successfully in the STMP server. However, if I send an email from an email client running in a computer located in the same local network (192.168.1.1/24), it doesn't succeed. Here below the error I get from Outlook Express:
The connection to the server has failed. Account 'localhost', Server '192.168.1.115'.
Protocol SMTP, Port: 25, Secure(SSL): No, Socket Error: 10061, Error Number: 0x800CCC0E
Just in case, I deactivated McAfee firewall in both PCs but I still get the same error.
Where can be the problem? Does it have anything to do with the asyncore.loop() method? Thanks!

Your server is running on the loopback interface:
server = CustomSMTPServer(('127.0.0.1', 25), None)
That interface is not reachable from any external network, only from the local machine.
You will need to start your email server on a real network interface (such as 192.168.1.115, based on the error message).
Also, I doubt you'll be able to retrieve any message anyway. You are running an SMTP server: it accepts messages over SMTP but will not provided POP3 / IMAP services, so you can't retrieve messages using a remote email client. The SMTP server can be used to store messages in a local file-based message store though (and en email client running on the same machine could retrieve messages from the file, if correctly formatted).

Related

Is there a way in python sockets (on the server) to know the hostname that a client connected to?

I'm relatively new to Python, so apologies for what me a simple question, I just cannot find the solution. First off, I am not looking for the client's hostname. My situation is that I have a simple socket server (basically this https://docs.python.org/3/library/socketserver.html#socketserver-tcpserver-example) which clients connect to. The exact server code is;
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8080
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
The clients connect successfully and are sending data which the server is receiving. My issue is that need to know the hostname that the client used to connect. The architecture will be like;
client1 will connect to client1.mydomain.net:8080
client2 will connect to client2.mydomain.net:8080
client3 will connect to client3.mydomain.net:8080
The DNS entry for client1.mydomain.net, client2.mydomain.net and client3.mydomain.net will all map to 123.123.123.123 so behind the scenes there is only one server.
The 3 clients will connect to their respective server and send their data. I have no control over the payload and I cannot augment it with a string or parm like "client=1".
So my question is, is there a way in python sockets (on the server) to know the hostname that a client connected to, so for example I know when I'm process data from client1.
Thanks!
Nothing at the TCP level reveals which hostname the client is connected to. This means there is no way for a generic TCP server to get this information.
Various protocols on top of TCP contains such information though. For example HTTP has a Host header so that different domains with different contents can be server on the same IP and port. TLS has the server_name extension in the TLS handshake so that the expected certificate can be given matching the hostname used by the client.
Thus, if you need this information you need to define your application protocol so that the client will include this information.

Unable to send or recieve emails from python aiosmtpd SMTP server, stuck at 250 ok [duplicate]

This question already has an answer here:
aiosmtpd - python smtp server
(1 answer)
Closed 3 months ago.
I had "successfully" made an SMTP server. The code works fine connecting to SMTP clients. But it is neither able to recieve emails nor send it. I tried with various test servers and also the standard gmail/yahoo etc.
Here is the code:
# Copyright 2014-2021 The aiosmtpd Developers
# SPDX-License-Identifier: Apache-2.0
import asyncio
from asyncio.base_events import Server
import logging
import aiosmtpd
from aiosmtpd.controller import DEFAULT_READY_TIMEOUT, Controller
import ssl
from aiosmtpd.smtp import Envelope, Session
from smtplib import SMTP as SMTPCLient
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('cert.pem', 'privkey.pem')
class ExampleHandler():
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
if address.endswith('#example.com'):
print('not relaying to that domain bro :(')
return '550 not relaying to that domain'
envelope.rcpt_tos.append(address)
print(address+" "+"is added to rcpt_tos")
# Make an envelope for the recipient with the same content.
return '250 OK'
# async def handle_EHLO(self, server, session, envelope):
# print('EHLO from %s' % envelope.mail_from)
# return '250-Hello, how are you?\n250-I am fine\n250 HELP'
async def handle_DATA(self, server, session, envelope):
print('Message from %s' % envelope.mail_from)
print('Message for %s' % envelope.rcpt_tos)
print('Message data:\n')
for ln in envelope.content.decode('utf8', errors='replace').splitlines():
print(f'> {ln}'.strip())
print()
print('End of message')
# Dump the contents of envelope.content to a file.
fi=open('./mailbox/firstletter.txt','w')
fi.write(envelope.content.decode('utf8', errors='replace'))
fi.close()
# print everything in DATA.
# Send the envelope to the recipient.
return '250 Message will be delivered'
#Define Relay server.
async def amain(loop):
cont = Controller(ExampleHandler(),hostname='x.x.x.x', port=25, server_hostname='Galam Limited',ready_timeout=5000)
# Combining ExampleHandler and Controller into a single Controller.
cont.start()
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
loop = asyncio.get_event_loop()
loop.create_task(amain(loop=loop))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
You can test the server reachability . I am stuck and spent 2 whole days to no avail. The issue is definetely not connectivity, I put the port 25 open. Made sure there are no external issues with godaddy either. Any help will be appreicated.
Edit:1
A quick peak at the wire shark data shows absolutely no packet is being transmitted to the outside when I run the client script.
Here is the clinet script I used for testing.
from smtplib import SMTP as Client
from aiosmtpd.controller import Controller
class controller:
hostname='192.168.1.33'
port=25
client = Client(controller.hostname, controller.port)
r = client.sendmail('a#galam.in', ['tester#192.168.1.200'], """\
From: Anne Person <anne#galam.in>
To: Bart Person <tester#192.168.1.200>
Subject: A test
Message-ID: <ant>
Hi Bart, this is Anne.
""")
SMTP 250 code means that a successful connection has been established however the remote host you are sending mails to might have categorized the domain the mail is being sent from as not legitimate.
This can happen if your domain is not authenticated/verified.
You can relay your messages through a trusted SMTP service like sendgrid
You can also check if your domain is verified by sending a mail from your service to check-auth#verifier.port25.com. Port25 is an automated tool that verified your DNS records, SPF records etc.
Hope this works for you!

How do I send an email to my python server?

I've written a small smtp server in python (taken from the smtpd docs):
import smtpd
import asyncore
class MySMTPServer(smtpd.SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
print 'Receiving message from:', peer
print 'Message addressed from:', mailfrom
print 'Message addressed to :', rcpttos
print 'Message length :', len(data)
return
server = MySMTPServer(('127.0.0.1', 587), None)
asyncore.loop()
I want to be able to send an email from my gmail account (or whatever email provider) to this server. Here's what I've done so far:
Write an MX record on an A-Level domain
Throw the server up on a box that has port 587 opened
Send an email from gmail to someone#myaleveldomain.com
Profit?
Step 4 hasn't really come through. I can't find any logs that offer any info into what happened, according to my server logs the message from gmail never arrived.
Am I doing something wrong? Please help!

How to making the smtlib.SMTP synchronous functions

I am a newbie to python programming. I am writing small smtp client for testing the POSTFIX smtp server implementation. I have used python smtplib for the same. Here is the code snippet.
import smtplib
def smtpTest(serverStr, mode=1):
servername = serverStr
server = smtplib.SMTP(servername, 25)
try:
server.set_debuglevel(True)
server.ehlo()
# If we can encrypt this session, do it
if server.has_extn('STARTTLS'):
server.docmd('STARTTLS\r\n RSET')
finally:
print "Closing the smtp session ...."
server.quit()
if __name__ == "__main__":
print "Closing the session now ..."
smtpTest(<ip address of smtp server>, 1)`
I am using the docmd() which should for the smtp server response. I am trying to check the smtp server behavior for the command 'STARTTLS\r\n RSET'.
Response details:-
My expectation is that the smtp server, if vulnerable, should give 2 response codes in sequence. One for the STARTTLS and other for RSET commands. My observation is that the server gets ready with tls tunnel and then the code enters in the finally block to close the session. So my conclusion is that the server is not vulnerable to STARTTLS.
My query:-
If I reverse the command string as 'RSET\r\n STARTTLS', I get the 2 response codes. With the reverse string of resetting and then starting tls, the quit function call ends the session and the command display for starttls appears after the client sends the quit command. I wanted to synchronize the call of quit only after I get the complete response from the server. In this case, the first being for RSET and then for STARTTLS.
Any pointers will be of great help.

Send message to localhost using XMPP in python

I have created a program to send chat messages via socket between two ports in localhost.
I need a third client who uses xmpp protocol to connect to localhost and sent message to here.When i run my server in terminal it shows this third client as connected
My code is given below:
import xmpp
msg='how r u :)'
client = xmpp.Client('localhost')
print "clienttttttttttttttttttt",client
con=client.connect(server=('localhost',5000))
#client.auth(username, passwd, 'botty')
#client.sendInitPresence()
message = xmpp.Message('localhost', msg)
print "messageeeeeeeeeeeeeeeeeeee",message
message.setAttr('type', 'chat')
client.send(message)
when i execute this code this error occurs
Registering protocol "error" as <class 'xmpp.protocol.Protocol'>(http://etherx.jabber.org/streams)
DEBUG: socket sent <?xml version='1.0'?>
<stream:stream xmlns="jabber:client" to="localhost" version="1.0" xmlns:stream="http://etherx.jabber.org/streams" >
Am using python xmpppy library.What is the issue here.How will i send my message to localhost which uses socket to send messages.Please help????

Categories

Resources