03 June 2021

From time to time I need to simulate sending email via bash script or a specific software.

I found a mock SMTP server that perfectly fit my needs mantained in james SMTP server:

To startup locally is very simple:

docker run --rm -p 2525:25 -p 8000:8000 linagora/mock-smtp-server

Above you could find examples of succesfully and failed, by a specific rule, delivering e-mail.

Case successfully deliver e-mail

docker run -d linagora/mock-smtp-server && docker exec -it $(docker ps | grep mock-smtp-server | head -1 | awk '{print $1}') bash

# apt update && apt install -y python

# curl --GET http://127.0.0.1:8000/smtpMails
[]

At the moment there are no email stored in mock server mail.
In order to send email we use python for a simple example:

# python
Python 2.7.13 (default, Apr 16 2021, 14:02:03) 
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import smtplib
>>> server = smtplib.SMTP(host='127.0.0.1', port=25)
>>> server.sendmail(from_addr='my@example.com', to_addrs='you@example.com', msg='Subject: My mail subject\n\nHello World!!!')
{}
>>> server.quit()
(221, 'Bye')
>>> exit()

# curl --GET http://127.0.0.1:8000/smtpMails
[{"from":"my@example.com","recipients":["you@example.com"],"message":"Received: from [172.17.0.2] (localhost [127.0.0.1])\r\n        by 6fc4bb93a031\r\n        with SMTP (SubEthaSMTP 3.1.7) id KP9AQRFY\r\n        for you@example.com;\r\n        Sat, 29 May 2021 05:11:31 +0000 (UTC)\r\nSubject: My mail subject\r\n\r\nHello World!!!\r\n"}]

As expected the API show the email sent via python.

Case failed deliver e-mail

docker run -d linagora/mock-smtp-server && docker exec -it $(docker ps | grep mock-smtp-server | head -1 | awk '{print $1}') bash

# apt update && apt install -y python

# curl --GET http://127.0.0.1:8000/smtpMails
[]

At the moment there are no email stored in mock server mail.
Set a rule that response with a failed deliver:

# curl -X PUT -H "Content-Type: application/json" -d '[{"command": "MAIL FROM","condition": {"operator": "contains","matchingValue": "fail-deliver-case"},"response": {"code": 521,"message": "Server does not accept mail"}}]' http://127.0.0.1:8000/smtpBehaviors

# curl --GET http://127.0.0.1:8000/smtpBehaviors
[{"condition":{"operator":"contains","matchingValue":"fail-deliver-case"},"response":{"code":521,"message":"Server does not accept mail"},"numberOfAnswer":null,"command":"MAIL FROM"}]

The rule is set correctly, emulate failed send mail scenario using python:

# python
Python 2.7.13 (default, Apr 16 2021, 14:02:03) 
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import smtplib
>>> server = smtplib.SMTP(host='127.0.0.1', port=25)
>>> server.sendmail(from_addr='fail-deliver-case@example.com', to_addrs='you@example.com', msg='Subject: My mail subject\n\nHello World!!!')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/smtplib.py", line 736, in sendmail
    raise SMTPSenderRefused(code, resp, from_addr)
smtplib.SMTPSenderRefused: (521, 'Server does not accept mail', 'fail-deliver-case@example.com')
>>> server.quit()
(221, 'Bye')
>>> exit()

# curl --GET http://127.0.0.1:8000/smtpMails
[]

As expected the SMTP server response with error in sending email and it is not stored.

References