aio-libs / aiosmtpd

A reimplementation of the Python stdlib smtpd.py based on asyncio.
https://aiosmtpd.aio-libs.org
Apache License 2.0
312 stars 95 forks source link

SMTP AUTH extension not supported by server. #283

Open febriyan1302 opened 2 years ago

febriyan1302 commented 2 years ago

hello, i'am using aiosmtpd as a server proxy mail, i want analyze traffic mail, it's normal if i'm not use Authentication, i can send a mail. but if i use authenticator on Controller my client side give me an error "SMTP AUTH extension not supported by server."

i try example of aiosmtpd/examples/authenticated_relayer/server.py , but same result.

python version : 3.6 OS : MacOS BigSur 11.5.2 , i try running on docker with base ubuntu 20.04, same result on me

Server Code :

    class Authenticator:
        def __init__(self, auth_database):
            self.auth_db = Path(auth_database)

        def __call__(self, server, session, envelope, mechanism, auth_data):
            fail_nothandled = AuthResult(success=False, handled=False)
            if mechanism not in ("LOGIN", "PLAIN"):
                return fail_nothandled
            if not isinstance(auth_data, LoginPassword):
                return fail_nothandled
            username = auth_data.login
            password = auth_data.password
            hashpass = password
            conn = sqlite3.connect(self.auth_db)
            curs = conn.execute(
                "SELECT hashpass FROM userauth WHERE username=?", (username,)
            )
            hash_db = curs.fetchone()
            conn.close()
            if not hash_db:
                return fail_nothandled
            if hashpass != hash_db[0]:
                return fail_nothandled
            return AuthResult(success=True)

    logging.basicConfig(level=logging.DEBUG)
    controller = Controller(
        MailProxyHandler(
            host=config.get('remote', 'host'),
            port=config.getint('remote', 'port', fallback=25),
            auth=remote_auth,
            use_ssl=config.getboolean('remote', 'use_ssl', fallback=False),
            starttls=config.getboolean('remote', 'starttls', fallback=False),
        ),
        hostname=config.get('local', 'host', fallback='127.0.0.1'),
        port=config.getint('local', 'port', fallback=25),
        authenticator=Authenticator(DB_AUTH),
        auth_required=True
    )
    controller.start()

    print("Mail proxy started ...")
    print("Remote Server : " + config.get('remote', 'host'))
    while controller.loop.is_running():
        sleep(0.2)

Client Code :

port = 8465  
smtp_server = "127.0.0.1"
sender_email = "lalala@gmail.com"  # Enter your address
to = "FF <lalala@gmail.com>"  # Enter receiver address
cc = ["lalala@lalala.co.id", "YOYO HE <lalala@lalala.co.id>"]
bcc = "lalala@gmail.com"

text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"
html = """\
<html>
  <head></head>
  <body>
    <p>Hi!<br>
       How are you?<br>
       Here is the <a href="http://www.python.org">link</a> you wanted.
    </p>
  </body>
</html>
"""

part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')

msg = MIMEMultipart()
msg['Subject'] = "This is subject"
msg['From'] = 'hehehe@gmail.com'
msg['To'] = to
msg['Cc'] = ", ".join(cc)

msg.attach(part1)
msg.attach(part2)

rcpt = [to]
with smtplib.SMTP(smtp_server, port) as server:
    server.connect(smtp_server, port)
    server.set_debuglevel(1)
    server.login("user1", "password1")
    server.sendmail(sender_email, rcpt, msg.as_string())

Server LOG :

Screen Shot 2021-09-14 at 16 43 13

Client LOG :

Screen Shot 2021-09-14 at 16 43 27

Thank you for your help

febriyan1302 commented 2 years ago

Update :

i try to setup TLS with following this tutorial

and the result is :

Screen Shot 2021-09-16 at 19 34 48

i dont understand this logic

Screen Shot 2021-09-16 at 19 40 00

my code :

Screen Shot 2021-09-16 at 19 37 49

please help gays

zcy382725 commented 2 years ago

Same issue???

File "/usr/lib/python3.9/smtplib.py", line 716, in login raise SMTPNotSupportedError( smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server.

l86610273 commented 2 years ago

Hello

I have the same problem

Have you solved it

febriyan1302 commented 2 years ago

Hello

I have the same problem

Have you solved it

nope bro

Same issue???

File "/usr/lib/python3.9/smtplib.py", line 716, in login raise SMTPNotSupportedError( smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server.

yes same issue

febriyan1302 commented 2 years ago

hallo @zcy382725 @l86610273

after understanding the aiosmtpd library and following this code , i solve my problem.

so, i don't need authentication , what we need is handle_AUTH

Correct me if i am wrong

waynew commented 2 years ago

(obviously) that's the approach that I took :)

It's probably worth us improving the documentation for how to accomplish such a thing :thinking:

I'm not sure if we should create a default implementation of AUTH handling, or not, though.

pepoluan commented 2 years ago

Hi @febriyan1302 , where does MailProxyHandler comes from?

In the documentation here, handle_AUTH is mostly needed to implement a custom AUTH handling; custom AUTH mechanisms can simply implement auth_MECHANISM callable, as described here.

A sample for a Mail Relay Proxy is provided in examples/authenticated_relayer

febriyan1302 commented 2 years ago

Hi @febriyan1302 , where does MailProxyHandler comes from?

In the documentation here, handle_AUTH is mostly needed to implement a custom AUTH handling; custom AUTH mechanisms can simply implement auth_MECHANISM callable, as described here.

A sample for a Mail Relay Proxy is provided in examples/authenticated_relayer

Hi @pepoluan :) (akhirnya dibales juga sama yg punya haha, salam kenal om)

so, simply the MailProxyHandler is a class that have function async def handle_DATA(self, server, session, envelope) for forward mail to SMTP or API (what i need).

your sample on examples/authenticated_relayer give me error like this and actualy i dont understand why status return MISSING

Screen Shot 2021-10-19 at 15 49 45
cbrand commented 2 years ago

I ran into this too when I tried to connect to an SMTP server and I think I found the root cause.

The issue / missing link is in the implementation of the ehlo handler: https://github.com/aio-libs/aiosmtpd/blob/master/aiosmtpd/smtp.py#L833

Here the AUTH extension is only sent if there exists a valid TLS connection. This makes sense, especially on publicly hosted services. Further checks have seen that the TLS check only works if a connection is established via STARTTLS.

Without this no authentication support as documented in the docs is possible.

Knowing this, and explicitly initiating a connection with STARTTLS seems to work:

import smtplib, ssl

user = "test"
password = "secretpw"

# Create a secure SSL context
context = ssl.create_default_context()

sender_email = "test@example.com"
receiver_email = "receiver@example.com"
message = """\
From: test@example.com
To: receiver@example.com
Subject: Hi there

This message is sent from Python."""

with smtplib.SMTP("smtp.example.com", 568) as server:
    server.helo()
    server.ehlo()
    server.starttls(context=context)
    server.login(user, password)
    server.sendmail(sender_email, receiver_email, message)

It doesn't seem to work for TLS connections which are not initiated with STARTTLS though if I read the code correctly.

l86610273 commented 2 years ago

你好@ zcy382725 @ l86610273

了解 aiosmtpd 库并遵循此代码后,我解决了我的问题。

所以,我不需要authentication,我们需要的是handle_AUTH

如果我错了,请纠正我

(obviously) that's the approach that I took :)

It's probably worth us improving the documentation for how to accomplish such a thing 🤔

I'm not sure if we should create a default implementation of AUTH handling, or not, though.

Hello Can you give your sample code thanks

febriyan1302 commented 2 years ago

examples/authenticated_relayer

from this you just need adding TLS, it works on me

SMTP Server (see tls_context)

Screen Shot 2021-12-10 at 14 10 23

SMTP Client

Screen Shot 2021-12-10 at 14 11 43
ludndev commented 4 days ago

Anyone trying to use auth without TLS setup, add to Controller auth_require_tls=False as in

image