SMTP to MQTT Add-on

Thanks for your huge help. I will try to configure everything…just one last thing about the Log. I think there is some error even though I seem to receive the email.

 warn("Requiring AUTH while not requiring TLS "
auth_required == True but auth_require_tls == False
2023-02-23 16:29:58,452 - smtp2mqtt - INFO - main thread - dummy-authenticating whatever credentials are offered...
Session.login_data is deprecated and will be removed in version 2.0
2023-02-23 16:29:58,546 - smtp2mqtt - INFO - ca2db341 - Message from [email protected]
2023-02-23 16:29:58,548 - smtp2mqtt - DEBUG - ca2db341 - Message data (truncated): From: ""<[email protected]>
To: <[email protected]>
Subject: =?UTF-8?B?VGVzdCBlLW1haWw=?=
Mime-Version: 1.0
Content-Type: multipart/mixed;
    boundary=PartBoundary12345678

--PartBoundary12345678
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: base64

SWYgeW91IHJlY2VpdmUgdGhpcyBlLW1haWwgeW91IGhhdmUgc3VjY2Vzc2Z1bGx5IHNldCB1cCBhbmQgdGVzdGVkIHRoZSBlLW1haWwgYWxlcnQgZnJvbSB5b3VyIElQQw==

--PartBoundary12345678--

2023-02-23 16:29:58,600 - smtp2mqtt - DEBUG - ca2db341 - got message header From: [email protected]
2023-02-23 16:29:58,600 - smtp2mqtt - DEBUG - ca2db341 - got message header To: [email protected]
2023-02-23 16:29:58,601 - smtp2mqtt - DEBUG - ca2db341 - got message header Subject: Test e-mail
2023-02-23 16:29:58,601 - smtp2mqtt - DEBUG - ca2db341 - got message header Mime-Version: 1.0
2023-02-23 16:29:58,602 - smtp2mqtt - DEBUG - ca2db341 - got message header Content-Type: multipart/mixed; boundary="PartBoundary12345678"
2023-02-23 16:29:58,607 - smtp2mqtt - DEBUG - ca2db341 - got body header Content-Type: text/plain; charset="utf-8"
2023-02-23 16:29:58,607 - smtp2mqtt - DEBUG - ca2db341 - got body header Content-Transfer-Encoding: base64
2023-02-23 16:29:58,612 - smtp2mqtt - DEBUG - ca2db341 - stored [If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC] as the content
2023-02-23 16:29:58,615 - smtp2mqtt - DEBUG - ca2db341 - Publishing [{"uuid": "ca2db341", "headers": {"from": "[email protected]", "to": "[email protected]", "subject": "Test e-mail", "mime-version": "1.0", "content-type": "multipart/mixed; boundary=\"PartBoundary12345678\""}, "mime_parts": [{"best_guess": "message body", "headers": {"content-type": "text/plain; charset=\"utf-8\"", "content-transfer-encoding": "base64"}, "content": "If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC"}, {"best_guess": "message body", "headers": {"content-type": "text/plain; charset=\"utf-8\"", "content-transfer-encoding": "base64"}, "content": "If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC"}]}] to smtp2mqtt/[email protected]
2023-02-23 16:29:59,551 - smtp2mqtt - ERROR - ca2db341 - Failed publishing
Traceback (most recent call last):
  File "/app/smtp2mqtt.py", line 152, in mqtt_publish
    publish.single(
  File "/usr/lib/python3.10/site-packages/paho/mqtt/publish.py", line 240, in single
    multiple([msg], hostname, port, client_id, keepalive, will, auth, tls,
  File "/usr/lib/python3.10/site-packages/paho/mqtt/publish.py", line 176, in multiple
    client.connect(hostname, port, keepalive)
  File "/usr/lib/python3.10/site-packages/paho/mqtt/client.py", line 914, in connect
    return self.reconnect()
  File "/usr/lib/python3.10/site-packages/paho/mqtt/client.py", line 1044, in reconnect
    sock = self._create_socket_connection()
  File "/usr/lib/python3.10/site-packages/paho/mqtt/client.py", line 3685, in _create_socket_connection
    return socket.create_connection(addr, timeout=self._connect_timeout, source_address=source)
  File "/usr/lib/python3.10/socket.py", line 824, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/usr/lib/python3.10/socket.py", line 955, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name does not resolve
2023-02-23 16:29:59,571 - smtp2mqtt - DEBUG - ca2db341 - SKIP relaying the original email

OK, you’re getting there… :slight_smile:

Looks like your camera is configured correctly and this addon is working, however it is having trouble publishing to MQTT.

Do you have an MQTT broker running & available? It’s common to just install the Mosquitto addon. If you have that then you’ll need to look at its config and make note of the username and password you configured for it, then come back to the config for this addon and enter those in the appropriate fields, then restart it & try again.

If you don’t have the Mosquitto addon then you’ll need some kind of MQTT broker on your network and you’ll need to enter its host/IP in the config of this addon so it knows where to publish, along with any username & password, etc.

Regardless of which MQTT broker you use, you’ll also need the MQTT integration (so home assistant can incorporate MQTT events & utilize them).

It’s been a while since I have installed the MQTT integration but if I remember right, when you use the Mosquitto addon, installing and configuring the MQTT integration is pretty painless (you may need to make note of that username & password again).

Now I think I have no more errors. I have mqtt installed on docker in debian. I had to enter the home assistant’s ip address. the username and password were already correct

2023-02-23 17:01:53,382 - smtp2mqtt - INFO - main thread - dummy-authenticating whatever credentials are offered...
Session.login_data is deprecated and will be removed in version 2.0
2023-02-23 17:01:53,472 - smtp2mqtt - INFO - f1ef10d7 - Message from [email protected]
2023-02-23 17:01:53,473 - smtp2mqtt - DEBUG - f1ef10d7 - Message data (truncated): From: ""<[email protected]>
To: <[email protected]>
Subject: =?UTF-8?B?VGVzdCBlLW1haWw=?=
Mime-Version: 1.0
Content-Type: multipart/mixed;
    boundary=PartBoundary12345678

--PartBoundary12345678
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: base64

SWYgeW91IHJlY2VpdmUgdGhpcyBlLW1haWwgeW91IGhhdmUgc3VjY2Vzc2Z1bGx5IHNldCB1cCBhbmQgdGVzdGVkIHRoZSBlLW1haWwgYWxlcnQgZnJvbSB5b3VyIElQQw==

--PartBoundary12345678--

2023-02-23 17:01:53,508 - smtp2mqtt - DEBUG - f1ef10d7 - got message header From: [email protected]
2023-02-23 17:01:53,509 - smtp2mqtt - DEBUG - f1ef10d7 - got message header To: [email protected]
2023-02-23 17:01:53,510 - smtp2mqtt - DEBUG - f1ef10d7 - got message header Subject: Test e-mail
2023-02-23 17:01:53,511 - smtp2mqtt - DEBUG - f1ef10d7 - got message header Mime-Version: 1.0
2023-02-23 17:01:53,512 - smtp2mqtt - DEBUG - f1ef10d7 - got message header Content-Type: multipart/mixed; boundary="PartBoundary12345678"
2023-02-23 17:01:53,520 - smtp2mqtt - DEBUG - f1ef10d7 - got body header Content-Type: text/plain; charset="utf-8"
2023-02-23 17:01:53,521 - smtp2mqtt - DEBUG - f1ef10d7 - got body header Content-Transfer-Encoding: base64
2023-02-23 17:01:53,530 - smtp2mqtt - DEBUG - f1ef10d7 - stored [If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC] as the content
2023-02-23 17:01:53,536 - smtp2mqtt - DEBUG - f1ef10d7 - Publishing [{"uuid": "f1ef10d7", "headers": {"from": "[email protected]", "to": "[email protected]", "subject": "Test e-mail", "mime-version": "1.0", "content-type": "multipart/mixed; boundary=\"PartBoundary12345678\""}, "mime_parts": [{"best_guess": "message body", "headers": {"content-type": "text/plain; charset=\"utf-8\"", "content-transfer-encoding": "base64"}, "content": "If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC"}, {"best_guess": "message body", "headers": {"content-type": "text/plain; charset=\"utf-8\"", "content-transfer-encoding": "base64"}, "content": "If you receive this e-mail you have successfully set up and tested the e-mail alert from your IPC"}]}] to smtp2mqtt/[email protected]
2023-02-23 17:01:53,546 - smtp2mqtt - DEBUG - f1ef10d7 - SKIP relaying the original email

That looks good to me.

Your emails should be publishing to that MQTT broker now.

All you need is to make sure home assistant is aware of the broker (via the MQTT integration) and then you should be able to start defining sensors, automations, etc. that utilize the topic being published to.

everything works perfectly!! thanks for your patience

No problem, glad to hear it is working for you :slight_smile:

thanks again for the help! I have only two things to ask… the first is that I find the smtp2 folder on media which is always full of images that I have to delete after every day but this is not a big problem… the problem is that when I get the notification on the phone and I open it directs me to the home screen of the home assistant app and therefore I have to go manually to the media folder and look for the file corresponding to the date and time but which with the presence of so many files is difficult to find … there is no is there a way to open the notification and direct me to the full screen image?

I researched this a little, found this post:

How to open /media image via relative URL in clickAction?

So I added a ‘clickAction’ in my automation, just below the ‘image’ that was already there, like so:

data:
    image: >-
      {{trigger.payload_json.mime_parts|selectattr('saved_file_name','defined')|map(attribute='saved_file_name')|first|replace('/share','/media')}}
    clickAction: >-
      {{trigger.payload_json.mime_parts|selectattr('saved_file_name','defined')|map(attribute='saved_file_name')|first|replace('/share','/media')}}

And it looked like it was going to work, but then all I got was a ‘401 unauthorized’ which is what they OP was saying in that post.

So then I followed the open issues on it:

https://github.com/home-assistant/android/issues/2684

https://github.com/home-assistant/android/pull/3232

And it looks like they put a fix into the current beta release of the Android app:

https://github.com/home-assistant/android/releases/tag/beta-3232-aaef2549

I downloaded the .apk for that beta & tried it, still didn’t work.

So at this time it looks like there are provisions for doing something like this, but it doesn’t currently work, sorry.

As for cleaning up the share folder with all the images, I have a scheduled automation that runs a Shell Command service nightly.

The shell command itself is simple:

find /share/smtp2mqtt/ -maxdepth 1 -type f -mtime +1 -exec rm {} \;

This seems to work well, keeps the files trimmed down to about a couple days’ worth.

Ok thanks!I hope this problem is solved because it would be a very useful thing

is there a possibility to rename the files in order to be more recognizable? for example ordering them with a starting number…it’s really hard to find the picture by phone because they are ordered randomly

Apologies for taking so long to reply to this, been very busy lately.

I did think about this for a bit & decided against modifying the add-on to re-name since others may want something different and it could get out of hand trying to find a way to make it generic enough for everyone.

Instead I had another thought - I believe it would be relatively simple to use the Shell Command integration to rename the files after they are written to disk.

It could be an action in the automation to call a shell command that simply does an mv from the current file name to whatever file name you wish.

Probably do that early-on, then reference the new file name in the notification service (since the old file name won’t exist anymore after the mv).

So, it looks like my camera updated its firmware and I can get smtp to Gmail to work. However, when I try this addon I’m getting some errors. The camera throws the same error 400, but there’s some new stuff in the logs now:

/usr/lib/python3.10/site-packages/aiosmtpd/smtp.py:372: UserWarning: Requiring AUTH while not requiring TLS can lead to security vulnerabilities!
  warn("Requiring AUTH while not requiring TLS "
auth_required == True but auth_require_tls == False
('192.168.168.125', 61559) unrecognised: e#

Is there anything I can do to hopefully get this working?

1 Like

I’m getting the exact same problem. I tried to configure this add-on with with my Reolink Argos Eco camera but every time I send a test email, I get a 400 error and this is the only message in the logs.

I found the problem with my Reolink Argos Eco camera.

It turns out that the camera sends an SMTP “HELO” message instead of “EHLO”. The SMTP library used by this add-on(“aiosmtpd”), considers the “HELO” not to be extended_smtp and later rejects the “AUTH LOGIN” command from the camera.

I don’t think there is an easy workaround other than modifying the “aiosmtpd” lib to force the extended_smtp mode for “HELO” as well.

Thank you for digging into the aiosmtp library & uncovering the difference between EHELO and HELO, that helps!

I can see in the code of the aiosmtp library where it is doing what you say, I can also see where it may be possible to override the HELO handler in this add-on to ‘turn on’ the extended smtp features, which may possibly be a work-around.

However, I am limited on time. I will try to make an effort in the next week or-so, no guarantees.

In the meantime, I’ll re-iterate my usual go-to - I know the password field in the camera web UI is marked required but I own several different Reolink devices and they all let me both test & save email settings when I leave that field blank and I am able to use this add-on with ‘SMTP Auth Required’ turned off, with no issues.

Could you please try again to leave the password field blank? Don’t forget to turn off SMTP auth in the add-on configuration as well.

Thanks again for doing the research!

I ran into this same HELO vs EHLO issue trying to use this add-on for a Cummins standby generator that sends events as emails.
As suggested the problem was fixed by adding the following method to SMTP2MQTTHandler:

    async def handle_HELO(self, server, session, envelope, hostname):
        session.extended_smtp = True
        session.host_name = server.hostname
        status = '250 {}'.format(server.hostname)
        return status

Good evening, I need help, I’ve been trying for a long time but I can’t get the images from my camera to publish on mqtt… With PowerShell Test I can publish but when my camera send image email I get the following error:

2024-03-21 23:16:02,254 - smtp2mqtt - DEBUG - d397f285 - SKIP publish attachment data
2024-03-21 23:16:02,255 - smtp2mqtt - INFO - d397f285 - Saving attachment to /share/smtp2mqtt/[email protected]/d397f285_6129747_2024032123160201.jpg
2024-03-21 23:16:02,261 - smtp2mqtt - DEBUG - d397f285 - SKIP publish attachment data
2024-03-21 23:16:02,261 - smtp2mqtt - INFO - d397f285 - Saving attachment to /share/smtp2mqtt/[email protected]/d397f285_None
(‘192.168.1.11’, 46242) SMTP session exception
Traceback (most recent call last):
File “/usr/lib/python3.10/site-packages/aiosmtpd/smtp.py”, line 741, in _handle_client
await method(arg)
File “/usr/lib/python3.10/site-packages/aiosmtpd/smtp.py”, line 1460, in smtp_DATA
status = await self._call_handler_hook(‘DATA’)
File “/usr/lib/python3.10/site-packages/aiosmtpd/smtp.py”, line 473, in _call_handler_hook
status = await hook(self, self.session, self.envelope, *args)
File “/app/smtp2mqtt.py”, line 127, in handle_DATA
f.write(attachment.get_content())
TypeError: a bytes-like object is required, not ‘str’ <

This is one great addon! Thank you mate.

I do have a question though. Would it be possible to make an option to set a directory where attachments should be saved? It now defaults to share directory, which might be on SD card and with alot of attachments, this would not be best. If you could set a save directory on lets say network share, that would be awsome.

Thank you for a response.
V.

For anyone who might feel the need, I have ported the Add-On to be a standalone docker image. I had the need to run two instances of this addon, because I have some services that cannot handle smtp auth without tls (Authelia to be specific) while others are happy without tls combined with smtp auth…

The service has been tested with Authelia, Vaultwarden, OpenMediaVault and Opnsense/Monit SMTP-Notifications. All SMTP Messages were successfully transformed to MQTT Messages for further use in Home Assistant. (I am goingt to use it for Push Messages to the Companion App btw…)

Thanks bcastellucci for your work on this!

A basic docker-compose.yaml could look like this. Modify the settings as needed with the environment variables, furthermore the image is multi-arch, so choose it according your needs:

services:
  smtp2mqtt:
    image: ghcr.io/boecks/docker-smtp2mqtt-amd64:latest
    container_name: smtp2mqtt
    ports:
      - 25:25 
    environment:
      DEBUG: true
      SMTP_LISTEN_PORT: 25
      SMTP_AUTH_REQUIRED: true
      SMTP_RELAY_HOST: None
      SMTP_RELAY_PORT: None
      SMTP_RELAY_USER: None
      SMTP_RELAY_PASS: None
      SMTP_RELAY_TIMEOUT_SECS: 60
      SMTP_RELAY_STARTTLS: false
      MQTT_HOST: mosquitto
      MQTT_PORT: 1883
      MQTT_USER: user
      MQTT_PASS: password
      MQTT_TOPIC: smtp2mqtt
      PUBLISH_ATTACHMENTS: true
      SAVE_ATTACHMENTS: false
      SAVE_ATTACHMENTS_DIR: /share/smtp2mqtt
    volumes:
      - ./attachments:/share
    restart: always
    logging:
      driver: json-file
      options:
        max-size: 1m
        max-file: 1

I’m trying to set up this add-on, I got everything installed ok but when I configure my NVR to send e-mail I get an error in the NVR and in the the add-on I get this:

('192.168.0.70', 59987) unrecognised: DGVZDEB0ZXN0LMNVBQ==

In my NVR I need to set at least the user name I used [email protected]