blackhole.smtp

Provides the Smtp protocol wrapper.

class blackhole.smtp.Smtp(clients, loop=None)[source]

The class responsible for handling SMTP/SMTPS commands.

connection_made(transport)[source]

Tie a connection to blackhole to the SMTP protocol.

Parameters

transport (asyncio.transports.Transport) – The transport class.

async push(code, msg)[source]

Write a response code and message to the client.

Parameters
  • code (int) – SMTP code, i.e. 250.

  • msg (str) – The message for the SMTP code

get_auth_members()[source]

Get a list of available AUTH mechanisms.

Returns

A list of available authentication mechanisms.

Return type

list

lookup_auth_handler(line)[source]

Look up a handler for the received AUTH mechanism.

Parameters

line (str) – A line of data from a client.

Returns

A callable authentication mechanism.

Return type

blackhole.smtp.Smtp.auth_MECHANISM

Note

Using pass= as part of the auth data will trigger an authentication pass, using fail= will trigger an authentication failure.

async auth_UNKNOWN()[source]

Response to an unknown auth mechanism.

async help_AUTH()[source]

Send help for AUTH mechanisms.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async auth_LOGIN()[source]

Handle an AUTH LOGIN request.

>>> AUTH LOGIN
334 VXNlcm5hbWU6
>>> pass=letmein
235 2.7.0 Authentication successful
>>> AUTH LOGIN
334 VXNlcm5hbWU6
>>> fail=letmein
535 5.7.8 Authentication failed

Note

Using pass= as part of the auth data will trigger an authentication pass, using fail= will trigger an authentication failure.

async auth_CRAM_MD5()[source]

Handle an AUTH CRAM-MD5 request.

>>> AUTH CRAM-MD5
334 PDE0NjE5MzA1OTYwMS4yMDQ5LjEyMzI4NTE2...
>>> pass=letmein
235 2.7.0 Authentication successful
>>> AUTH CRAM-MD5
334 PDE0NjE5MzA1OTYwMS4yMDQ5LjEyMzI4NTE2...
>>> fail=letmein
535 5.7.8 Authentication failed

Note

Using pass= as part of the auth data will trigger an authentication pass, using fail= will trigger an authentication failure.

async auth_PLAIN()[source]

Handle an AUTH PLAIN request.

>>> AUTH PLAIN
334
>>> pass=letmein
235 2.7.0 Authentication successful
>>> AUTH PLAIN
334
>>> fail=letmein
535 5.7.8 Authentication failed
>>> AUTH PLAIN pass=letmein
235 2.7.0 Authentication successful
>>> AUTH PLAIN fail=letmein
535 5.7.8 Authentication failed

Note

Using pass= as part of the auth data will trigger an authentication pass, using fail= will trigger an authentication failure.

async timeout()[source]

Timeout a client connection.

Sends the 421 timeout message to the client and closes the connection.

https://kura.gg/blackhole/configuration.html#timeout

lookup_handler(line)[source]

Look up the SMTP VERB against a handler.

Parameters

line (str) – Look up the command handler to use from the data provided.

Returns

A callable command handler.

Return type

blackhole.smtp.Smtp.do_VERB, blackhole.smtp.Smtp.auth_MECHANISM, blackhole.smtp.Smtp.help_VERB

lookup_help_handler(parts)[source]

Look up a help handler for the SMTP VERB.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

Parameters

parts (list) – A list of command data, split on spaces.

Returns

A callable help handler.

Return type

blackhole.smtp.Smtp.help_VERB

lookup_verb_handler(verb)[source]

Look up a handler for the SMTP VERB.

Parameters

verb (str) –

Returns

A callable command handler.

Return type

blackhole.smtp.Smtp.do_VERB

async greet()[source]

Send a greeting to the client.

get_help_members()[source]

Get a list of HELP handlers for verbs.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

Returns

A list of available help handlers.

Return type

list

async do_HELP()[source]

Send a response to the HELP verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async help_HELO()[source]

Send help for HELO verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_HELO()[source]

Send response to HELO verb.

async help_EHLO()[source]

Send help for the EHLO verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_EHLO()[source]

Send response to EHLO verb.

async help_MAIL()[source]

Send help for the MAIL TO verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_MAIL()[source]

Send response to MAIL TO verb.

Note

Checks to see if SIZE= is passed, pass function off to have it’s size handled.

async help_RCPT()[source]

Send response to the RCPT TO verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_RCPT()[source]

Send response to RCPT TO verb.

async help_DATA()[source]

Send help for the DATA verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

process_header(line)[source]

Process dynamic switch email headers.

Reads x-blackhole-delay and x-blackhole-mode headers and re-configures on-the-fly how the email is handled based on these headers.

https://kura.gg/blackhole/dynamic-switches.html

Parameters

line (str) – An email header.

async response_from_mode()[source]

Send a response based on the configured response mode.

https://kura.gg/blackhole/dynamic-switches.html#dynamic-delay-switcheshttps://kura.gg/blackhole/configuration.html#mode

Response mode is configured in configuration file and can be overridden by email headers, if enabled.

async do_DATA()[source]

Send response to DATA verb and wait for mail data.

This method will also implement timeout management and handling after receiving the DATA command and no new data is received.

This method also implements the delay functionality, delaying a response after the final ‘rn.rn’ line. – https://kura.gg/blackhole/configuration.html#delayhttps://kura.gg/blackhole/dynamic-switches.html#dynamic-delay-switches

This method implements restrictions on message sizes. – https://kura.gg/blackhole/configuration.html#max-message-size

async do_STARTTLS()[source]

STARTTLS is not implemented.

async help_NOOP()[source]

Send help for the NOOP verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_NOOP()[source]

Send response to the NOOP verb.

async help_RSET()[source]

Send help for the RSET verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_RSET()[source]

Send response to the RSET verb.

A new message id is generated and assigned.

async help_VRFY()[source]

Send help for the VRFY verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_VRFY()[source]

Send response to the VRFY verb.

>>> VRFY pass=user@domain.tld
250 2.0.0 <[email protected]> OK
>>> VRFY fail=user@domain.tld
550 5.7.1 <[email protected]> unknown
>>> VRFY user@domain.tld
252 2.0.0 Will attempt delivery

Note

If the request contains ‘pass=’, the server will respond with code 250. If the request contains ‘fail=’, the server will respond with code 550. And finally, if neither flag is found, the server will respond with code 252.

async help_EXPN()[source]

Send help for the EXPN verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_EXPN()[source]

Handle the EXPN verb.

>>> EXPN fail=test-list
550 Not authorised
>>> EXPN list1
250-Shadow <[email protected]>
250-Wednesday <[email protected]>
250 Low-key Liesmith <[email protected]>
>>> EXPN list2
250-Jim Holden <[email protected]>
250-Naomi Nagata <[email protected]>
250-Alex Kamal <[email protected]>
250 Amos Burton <[email protected]>
>>> EXPN list3
250-Takeshi Kovacs <[email protected]>
250-Laurens Bancroft <[email protected]>
250-Kristin Ortega <[email protected]>
250-Quellcrist Falconer <[email protected]>
250-Virginia Vidaura <[email protected]>
250 Reileen Kawahara <[email protected]>
>>> EXPN all
250-Shadow <[email protected]>
250-Wednesday <[email protected]>
250-Low-key Liesmith <[email protected]>
250-Takeshi Kovacs <[email protected]>
250-Laurens Bancroft <[email protected]>
250-Kristin Ortega <[email protected]>
250-Quellcrist Falconer <[email protected]>
250-Virginia Vidaura <[email protected]>
250-Reileen Kawahara <[email protected]>
250-Jim Holden <[email protected]>
250-Naomi Nagata <[email protected]>
250-Alex Kamal <[email protected]>
250 Amos Burton <[email protected]>
>>> EXPN list-does-not-exist
550 Not authorised

Note

If EXPN contains ‘fail=’ or does not specify a mailing list the command will return a 550 code. Valid lists are: list1, list2, list3 and all.

async help_ETRN()[source]

Send help for the ETRN verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async do_ETRN()[source]

Send response to the ETRN verb.

async help_QUIT()[source]

Send help for the QUIT verb.

https://kura.gg/blackhole/communicating-with-blackhole.html#help

async close()

Close the connection from the client.

connection_lost(exc)

Client connection is closed or lost.

Parameters

exc (exc) – Exception.

data_received(data)

Called when some data is received.

The argument is a bytes object.

async do_QUIT()[source]

Send response to the QUIT verb.

Closes the client connection.

eof_received()

Called when the other end calls write_eof() or equivalent.

If this returns a false value (including None), the transport will close itself. If it returns a true value, closing the transport is up to the protocol.

flags_from_transport()

Adapt internal flags for the transport in use.

pause_writing()

Called when the transport’s buffer goes over the high-water mark.

Pause and resume calls are paired – pause_writing() is called once when the buffer goes strictly over the high-water mark (even if subsequent writes increases the buffer size even more), and eventually resume_writing() is called once when the buffer size reaches the low-water mark.

Note that if the buffer size equals the high-water mark, pause_writing() is not called – it must go strictly over. Conversely, resume_writing() is called when the buffer size is equal or lower than the low-water mark. These end conditions are important to ensure that things go as expected when either mark is zero.

NOTE: This is the only Protocol callback that is not called through EventLoop.call_soon() – if it were, it would have no effect when it’s most needed (when the app keeps writing without yielding until pause_writing() is called).

resume_writing()

Called when the transport’s buffer drains below the low-water mark.

See pause_writing() for details.

async wait()

Wait for data from the client.

Returns

A line of received data.

Return type

str

Note

Also handles client timeouts if they wait too long before sending data. – https://kura.gg/blackhole/configuration.html#timeout

async do_NOT_IMPLEMENTED()[source]

Send a not implemented response.

async help_UNKNOWN()[source]

Send available help verbs when an invalid verb is received.

async do_UNKNOWN()[source]

Send response to unknown verb.

property delay

Delay after the DATA command completes.

Value is in seconds, with a maximum value of 60 seconds.

https://kura.gg/blackhole/configuration.html#delayhttps://kura.gg/blackhole/dynamic-switches.html#dynamic-delay-switches

Returns

A delay time in seconds. Default: None.

Return type

int or None

property mode

How to respond to an email, based on configuration.

Response is configured in the configuration file or configured from email headers, if configured to allow that option.

https://kura.gg/blackhole/configuration.html#modehttps://kura.gg/blackhole/dynamic-switches.html#dynamic-mode-switches

Returns

A response mode.

Return type

str