Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AUTH LOGIN support #102

Closed
mdehus opened this issue May 19, 2017 · 2 comments · Fixed by #192
Closed

AUTH LOGIN support #102

mdehus opened this issue May 19, 2017 · 2 comments · Fixed by #192

Comments

@mdehus
Copy link

mdehus commented May 19, 2017

I'm looking to implement auth support. For some of the mechanisms, this requires the client supply additional information on a new line following the command after a prompt is received from the server. LOGIN for example will prompt with 334 Username (in base64) and then expect the username to be supplied after and will repeat this for password. Same for plain, the credentials follow the command as a response.

I am fairly new to asyncio in general, but didn't find an easy way I could implement this in a subclass of SMTP or a handler without having to copy a significant amount of code. Am I missing something here? If not, what would be a reasonable approach to addressing this?

Examples:
C: AUTH PLAIN
S: 334
C: dGVzdAB0ZXN0ADEyMzQ=
S: 235 Authentication successful

C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
C: avlsdkfj
S: 334 UGFzc3dvcmQ6
C: lkajsdfvlj
S: 535 Authentication failed

@Mortal
Copy link
Contributor

Mortal commented May 19, 2017

Be sure to have a look at PR #66 to see the ongoing effort on implementing AUTH.

To solve the issue of reading additional information on a new line, use yield from self._reader.readline() in your smtp_AUTH() method. You might do something like:

class AuthSMTP(aiosmtpd.smtp.SMTP):
    @asyncio.coroutine
    def smtp_AUTH(self, arg):
        if arg != 'PLAIN':
            yield from self.push('501 Syntax: AUTH PLAIN')
            return
        yield from self.push('334')
        try:
            second_line = yield from self._reader.readline()
        except (ConnectionResetError, asyncio.CancelledError) as error:
            # How to recover here?
            TODO
        try:
            second_line = second_line.rstrip(b'\r\n').decode('ascii')
        except UnicodeDecodeError:
            yield from self.push('500 Error: Challenge must be ASCII')
            return
        if second_line == 'dGVzdAB0ZXN0ADEyMzQ=':
            self.authenticated = True
            yield from self.push('235 Authentication successful')
        else:
            yield from self.push('535 Invalid credentials')

Of course, a bigger issue with implementing AUTH is changing the SMTP class to require authentication before issuing any other command, but that doesn't appear to be what you're asking about.

@warsaw warsaw added this to the later milestone Jul 6, 2017
@pepoluan
Copy link
Collaborator

This has been fully implemented in PR #192 , waiting to be Code Reviewed & Merged.

@pepoluan pepoluan linked a pull request Oct 22, 2020 that will close this issue
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants