Forward email message to remote smtp server in Python - python

I want to create a SMTP-Gateway that filters emails and redirects them to the remote SMTP server.
from smtpd import SMTPServer
from email.parser import Parser
class SMTPGateway(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
print('Processing message...')
email = Parser().parsestr(data)
for part in email.walk():
if part.get_content_maintype() == 'text':
text = part.get_payload()
# Process text
# forward email to upstream smtp server
With this code I can receive a message and process it. But I don't know how to forward the message to the remote server.
In my main program, I create the server like this:
localaddress = ('localhost', 3000)
remoteaddress = ('localhost', 9000)
gateway = SMTPGateway(localaddress, remoteaddress)
How can I redirect the message in process_message to the remote server?
The documentation of the SMTP-Server is very short:
https://docs.python.org/2/library/smtpd.html.
I could not find the answer there.

I found the answer myself.
from smtpd import SMTPServer
from email.parser import Parser
class SMTPGateway(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
print('Processing message...')
email = Parser().parsestr(data)
for part in email.walk():
if part.get_content_maintype() == 'text':
text = part.get_payload()
# Process text
# forward email to upstream smtp server
ip = self._remoteaddr[0]
port = self._remoteaddr[1]
server = SMTP(ip, port)
server.send_message(email)
server.quit()

Related

i been receiving this message: 530-5.7.0 Authentication Required. While doing some socket programming with the socket module on python

i am using the socket module and the ssl module from python, and i want to send an email using very basic socket programming, but every time i send a command MAIL FROM, the message: 530-5.7.0 Authentication Required appears. I am looking for a solution that does not use the smtplib module.
this is the code:
from socket import *
import ssl
menssagem = '\r\n Eu gosto de redes'
finMenssagem = '\r\n.\r\n'
mailServer = 'smtp.gmail.com'
mailPort = 465
context = ssl.create_default_context()
with create_connection((mailServer, mailPort)) as sock:
with context.wrap_socket(sock, server_hostname=mailServer) as clientSocket:
print(clientSocket.version())
recv = clientSocket.recv(1024).decode()
print(recv)
if recv[:3] != '220':
print('220 reply not received from server.')
heloCommand = 'HELO Alice\r\n'
clientSocket.send(heloCommand.encode())
recv1 = clientSocket.recv().decode()
print(recv1)
if recv1[:3] != '250':
print('250 reply not received from server.')
mailfromCommand = 'MAIL FROM: <arthursilvamatias#gmail.com>\r\n'
clientSocket.send(mailfromCommand.encode())
recv2 = clientSocket.recv().decode()
print(recv2)
Image o the code running:
my code
You are attempting to send outbound email using Gmail's service.
They are trying to protect your account by preventing unauthorized users from using it to send email, masquerading as you.
This link should explain what you need to do to authenticate: https://stackabuse.com/how-to-send-emails-with-gmail-using-python/#:%7E:text=As%20for%20the%20actual%20Python,com%27%2C%20465)%20server.

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!

Sending mail through Python SMTP Server

I am trying to build a small SMTP Server through which I can be able to send some messages. Looking at the smtpd library found that there was something. But I only was able to create a server that reads the email received, but never sent it to the address requested.
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)
return
server = CustomSMTPServer(('127.0.0.1', 1025), None)
asyncore.loop()
client:
import smtplib
import email.utils
from email.mime.text import MIMEText
# Create the message
msg = MIMEText('This is the body of the message.')
msg['To'] = email.utils.formataddr(('Recipient', 'recipient#example.com'))
msg['From'] = email.utils.formataddr(('Author', 'author#example.com'))
msg['Subject'] = 'Simple test message'
server = smtplib.SMTP('127.0.0.1', 1025)
server.set_debuglevel(True) # show communication with the server
try:
server.sendmail('author#example.com', ['myadress#gmail.com'], msg.as_string())
finally:
server.quit()
If you really want to do this
then check out the Twisted examples:
http://twistedmatrix.com/documents/current/mail/examples/index.html#auto0
I really don't recommend you write your own MTA (Mail Transfer Agent) as this is
a complex task with many edge cases and standards to have to worry about.
Use an existing MTA such as Postfix, Exim, or Sendmail.

Why Do I Keep getting SSL Error on Simple Mail Client Program? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Implementing Transport Layer Security in Python - Simple Mail Client
I keep getting this error...
ssl.SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib
...in a simple mail client assignment which is to open a connection with a google smtp server. The problem almost certainly seems to be in the way I am forming the ssl.wrap_socket() method here....
clientSocket = socket(AF_INET, SOCK_STREAM)
ssl_clientSocket = ssl.wrap_socket(clientSocket,
ca_certs = '/etc/ssl/certs/ca.pm',
cert_reqs = ssl.CERT_REQUIRED)
ssl_clientSocket.connect((mailserver, port))
.. but I can't really figure out exactly what the problem is, and I'm really not sure which .pm file to use in /etc/ssl/certs. I'm using ca.pm because I've seen it done that way in a few tutorials. Here is the remainder of the code for good measure....
from socket import *
import certifi
import ssl
msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"
# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver = "smtp.gmail.com"
port = 587
# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
ssl_clientSocket = ssl.wrap_socket(clientSocket,
ca_certs = '/etc/ssl/certs/ca.pm',
cert_reqs = ssl.CERT_REQUIRED)
ssl_clientSocket.connect((mailserver, port))
###################################################################
print "got to here 1"
###############################################################
recv = ssl_clientSocket.recv(1024)
print
print recv
# If the first three numbers of what we receive from the SMTP server are not
# '220', we have a problem
if recv[:3] != '220':
print '220 reply not received from server.'
# Send HELO command and print server response.
heloCommand = 'HELO Alice\r\n'
ssl_clientSocket.send(heloCommand)
recv1 = ssl_clientSocket.recv(1024)
print recv1
######################################################################
print "Got to here 2"
#####################################################################
# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv1[:3] != '250':
print '250 reply not received from server.'
# Send MAIL FROM command and print server response.
mailFromCommand = 'MAIL From: wgimson#gmail.com\r\n'
ssl_clientSocket.send(mailFromCommand)
recv2 = ssl_clientSocket.recv(1024)
print recv2
# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv2[:3] != '250':
print '250 reply not received from server.'
# Send RCPT TO command and print server response.
rcptToCommand = 'RCPT To: macyali#gmail.com\r\n'
ssl_clientSocket.send(rcptToCommand)
recv3 = ssl_clientSocket.recv(1024)
print recv3
# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv3[:3] != '250':
print '250 reply not received from server.'
# Send DATA command and print server response.
dataCommand = 'DATA\r\n'
ssl_clientSocket.send(dataCommand)
recv4 = ssl_clientSocket.recv(1024)
print recv4
# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv4[:3] != '250':
print '250 reply not received from server.'
# Send message data.
ssl_clientSocket.send(msg)
# Message ends with a single period.
ssl_clientSocket.send(endmsg)
# Send QUIT command and get server response.
quitCommand = 'QUIT\r\n'
ssl_clientSocket.send(quitCommand)
recv5 = ssl_clientSocket.recv(I1024)
print recv5
# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv5[:3] != '221':
print '221 reply not received from server.'
the error might be caused by a typo: '/etc/ssl/certs/ca.pm' -> '/etc/ssl/certs/ca.pem'
i.e., the system can't find ca.pm file
'/etc/ssl/certs/ca.pem' doesn't contain necessary CA certs.
You could download cacert.pem from http://curl.haxx.se/ca/cacert.pem (it is more current) or use ca_certs = certifi.where() (I see import certifi in your code), example:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import smtplib
import socket
import ssl
import sys
from email.header import Header
from email.mime.text import MIMEText
from getpass import getpass
import certifi # $ pip install certifi
login, password = 'user#gmail.com', getpass('Gmail password:')
ca_certs = certifi.where()
##ca_certs = 'cacert.pem' # $ wget http://curl.haxx.se/ca/cacert.pem
class SMTP_SSL(smtplib.SMTP_SSL):
"""Add support for additional ssl options."""
def __init__(self, host, port=0, **kwargs):
self.ssl_kwargs = kwargs.pop('ssl_kwargs', {})
self.ssl_kwargs['keyfile'] = kwargs.pop('keyfile', None)
self.ssl_kwargs['certfile'] = kwargs.pop('certfile', None)
smtplib.SMTP_SSL.__init__(self, host, port, **kwargs)
def _get_socket(self, host, port, timeout):
if self.debuglevel > 0:
print>>sys.stderr, 'connect:', (host, port)
new_socket = socket.create_connection((host, port), timeout)
new_socket = ssl.wrap_socket(new_socket, **self.ssl_kwargs)
self.file = smtplib.SSLFakeFile(new_socket)
return new_socket
# create message
msg = MIMEText('message body…', _charset='utf-8')
msg['Subject'] = Header('subject…', 'utf-8')
msg['From'] = login
msg['To'] = login
# send it via gmail
s = SMTP_SSL('smtp.gmail.com', timeout=10,
ssl_kwargs=dict(cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_SSLv3,
ca_certs=ca_certs))
s.set_debuglevel(1) # enable debug output
try:
s.login(login, password)
s.sendmail(msg['From'], msg['To'], msg.as_string())
finally:
s.quit()

Categories

Resources