Repository: Mailu/Mailu

Issue:
Unable to send an Public Announcement
## Environment & Versions
### Environment
 - docker-compose

### Versions
 - version 1.9

## Description
My mailu mail server is running as I expected it. Everything is working normally besides one admin function of it.
I am not able to use the Public Announcement. Doing so results in an error 502
I am using the mailu.env and docker-compose I created online for this.

## Replication Steps
I am logged in as administrator (my account has the role of global administrator as well as manager of the domain)
I choose option announcement under Menu Administration, fill in the Announcement- subject and body and select click on send button. After 30 secs I get an "502 Bad Gateway" message from nginx and no mail is being send
I have NO overrides options defined.

## Expected behaviour
I expected a mail to be send to all users of my domain with the context of the subject and body I entered
Instead I get an nginx error 502 page.

## Logs
I have exchanged my client IP adress with aaa.bbb.ccc.ddd and adjusted the domain to example.com in the logs underneath for privacy reasons. Rest is exactly as it is stated in the logs.

mailu-admin-1:
[2022-02-13 09:53:03 +0100] [9] [CRITICAL] WORKER TIMEOUT (pid:10)
[2022-02-13 09:53:04 +0100] [9] [WARNING] Worker with pid 10 was terminated due to signal 9
[2022-02-13 09:53:04 +0100] [29] [INFO] Booting worker with pid: 29

mailu-front-1:
2022/02/13 09:53:04 [error] 8#8: *3 upstream prematurely closed connection while reading response header from upstream, client: aaa.bbb.ccc.ddd, server: , request: "POST /admin/announcement HTTP/2.0", upstream: "http://192.168.203.6:80/admin/announcement", host: "mail.example.com", referrer: "https://mail.example.com/admin/announcement"

mailu-smtp-1:
2022-02-13T09:52:33.536923+01:00 b27dd03ea1f5 postfix/smtpd[371]: connect from mailu-admin-1.mailu_default[192.168.203.6]
2022-02-13T09:52:33.540236+01:00 b27dd03ea1f5 postfix/smtpd[371]: discarding EHLO keywords: PIPELINING
2022-02-13T09:53:04.866990+01:00 b27dd03ea1f5 postfix/smtpd[371]: disconnect from mailu-admin-1.mailu_default[192.168.203.6] ehlo=1 mail=1 quit=1 commands=3




Discussion:
This happened to me as well recently. I got timeouts too. (but on v1.8) If you have to get it done urgently: try again repeatedly! It sounds counterintuitive, but in this case trying the same thing over and over actually does lead to different outcomes. I don't know why, but I got mine sent.
> This happened to me as well recently. I got timeouts too. (but on v1.8) If you have to get it done urgently: try again repeatedly! It sounds counterintuitive, but in this case trying the same thing over and over actually does lead to different outcomes. I don't know why, but I got mine sent.

Thanks for your feedback. I have tried your advise but did not succeed getting any announcement out to "my users". 
I have even tried a newly installed VPS server without any extra firewall rules or other adjustments, but this seems the only part that is not working of mailu for me.

Could it be generic and no one else is using this ? Because I do not read others having this issue (only some old resolved similar issues)

I do hope it can be fixed, because I would like to start using mailu in production
I have pinpointed the start of the problem

It is this line 24 in /app/mailu/ui/views/base.py in mailu-front-1 when it goes wrong
`   user.sendmail(form.announcement_subject.data, form.announcement_body.data)`

If I comment it I do not get the 502 message and the expected flask success message, but of course also not the email ;-)
There seems to be something wrong with the function I think although I am no python/flask expert

I hope someone is willing to check/verify and maybe come with a solution.
I would also appreciate to hear if others are able to use this option successfull or is it just me ?

On a fresh 1.9 installation I cannot replicate this. Without reliable replicating steps it will be difficult to look into this.

Could you try again with a small test message? Possibly the issue is tied to the contents of the message.
This is how the SMTP logs look like for a successful attempt. For every user on my test server an email is send
```
smtp_1       | 2022-02-17T15:29:14.439769+00:00 967bafac904d postfix/smtpd[1613]: connect from mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.442145+00:00 967bafac904d postfix/smtpd[1613]: discarding EHLO keywords: PIPELINING
smtp_1       | 2022-02-17T15:29:14.535834+00:00 967bafac904d postfix/smtpd[1613]: 82CA418005E: client=mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.560068+00:00 967bafac904d postfix/cleanup[1616]: 82CA418005E: message-id=<>
smtp_1       | 2022-02-17T15:29:14.589978+00:00 967bafac904d postfix/qmgr[372]: 82CA418005E: from=<admin@test.example.com>, size=314, nrcpt=1 (queue active)
smtp_1       | 2022-02-17T15:29:14.590750+00:00 967bafac904d postfix/smtpd[1613]: disconnect from mailu_admin_1.mailu_default[192.168.203.6] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
smtp_1       | 2022-02-17T15:29:14.592501+00:00 967bafac904d postfix/smtpd[1613]: connect from mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.595564+00:00 967bafac904d postfix/smtpd[1613]: discarding EHLO keywords: PIPELINING
smtp_1       | 2022-02-17T15:29:14.709425+00:00 967bafac904d postfix/smtpd[1613]: AD2BC18005F: client=mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.748396+00:00 967bafac904d postfix/cleanup[1616]: AD2BC18005F: message-id=<>
smtp_1       | 2022-02-17T15:29:14.762164+00:00 967bafac904d postfix/qmgr[372]: AD2BC18005F: from=<admin@test.example.com>, size=313, nrcpt=1 (queue active)
smtp_1       | 2022-02-17T15:29:14.764959+00:00 967bafac904d postfix/smtpd[1613]: disconnect from mailu_admin_1.mailu_default[192.168.203.6] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
smtp_1       | 2022-02-17T15:29:14.772441+00:00 967bafac904d postfix/smtpd[1613]: connect from mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.775390+00:00 967bafac904d postfix/smtpd[1613]: discarding EHLO keywords: PIPELINING
smtp_1       | 2022-02-17T15:29:14.789028+00:00 967bafac904d postfix/lmtp[1617]: 82CA418005E: to=<admin@test.example.com>, relay=192.168.203.9[192.168.203.9]:2525, delay=0.31, delays=0.11/0.03/0.05/0.12, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.example.com> eLjxJ8ppDmJtBQAAMm7Psw Saved)
smtp_1       | 2022-02-17T15:29:14.803519+00:00 967bafac904d postfix/qmgr[372]: 82CA418005E: removed
smtp_1       | 2022-02-17T15:29:14.947601+00:00 967bafac904d postfix/smtpd[1613]: E705418005E: client=mailu_admin_1.mailu_default[192.168.203.6]
smtp_1       | 2022-02-17T15:29:14.965108+00:00 967bafac904d postfix/lmtp[1617]: AD2BC18005F: to=<test@test.example.com>, relay=192.168.203.9[192.168.203.9]:2525, delay=0.37, delays=0.17/0.04/0.01/0.15, dsn=2.0.0, status=sent (250 2.0.0 <test@test.example.com> YAx8MMppDmJtBQAAMm7Psw Saved)
smtp_1       | 2022-02-17T15:29:14.965600+00:00 967bafac904d postfix/qmgr[372]: AD2BC18005F: removed
smtp_1       | 2022-02-17T15:29:14.988799+00:00 967bafac904d postfix/cleanup[1616]: E705418005E: message-id=<>
smtp_1       | 2022-02-17T15:29:15.010396+00:00 967bafac904d postfix/qmgr[372]: E705418005E: from=<admin@test.example.com>, size=314, nrcpt=1 (queue active)
smtp_1       | 2022-02-17T15:29:15.010783+00:00 967bafac904d postfix/smtpd[1613]: disconnect from mailu_admin_1.mailu_default[192.168.203.6] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
smtp_1       | 2022-02-17T15:29:15.159711+00:00 967bafac904d postfix/lmtp[1618]: E705418005E: to=<test2@test.example.com>, relay=192.168.203.9[192.168.203.9]:2525, delay=0.38, delays=0.23/0.05/0.01/0.08, dsn=2.0.0, status=sent (250 2.0.0 <test2@test.example.com> ZXOoBMtpDmJxBQAAMm7Psw Saved)
smtp_1       | 2022-02-17T15:29:15.160152+00:00 967bafac904d postfix/qmgr[372]: E705418005E: removed
```
This is the relevant code that is used for sending the emails to every user:
https://github.com/Mailu/Mailu/blob/b73963aae5177770c64c8e04be7c11b00317f0a5/core/admin/mailu/models.py#L413

```
    def sendmail(self, subject, body):
        """ send an email to the address """
        f_addr = f'{app.config["POSTMASTER"]}@{idna.encode(app.config["DOMAIN"]).decode("ascii")}'
        with smtplib.SMTP(app.config['HOST_AUTHSMTP'], port=10025) as smtp:
            to_address = f'{self.localpart}@{idna.encode(self.domain_name).decode("ascii")}'
            msg = text.MIMEText(body)
            msg['Subject'] = subject
            msg['From'] = f_addr
            msg['To'] = to_address
            smtp.sendmail(f_addr, [to_address], msg.as_string())
```

The form code https://github.com/Mailu/Mailu/blob/b73963aae5177770c64c8e04be7c11b00317f0a5/core/admin/mailu/ui/views/base.py#L18

```
@ui.route('/announcement', methods=['GET', 'POST'])
@access.global_admin
def announcement():
    form = forms.AnnouncementForm()
    if form.validate_on_submit():
        for user in models.User.query.all():
            user.sendmail(form.announcement_subject.data,
                form.announcement_body.data)
        # Force-empty the form
        form.announcement_subject.data = ''
        form.announcement_body.data = ''
        flask.flash('Your announcement was sent', 'success')
    return flask.render_template('announcement.html', form=form)
```

In your log we can see that a connection is made to smtp. But for some reason the email is not send. There appears to be some kind of timeout after 30 seconds. Sending the email should take less than a second.
> But for some reason the email is not send. There appears to be some kind of timeout after 30 seconds.

100% exact situation as with my post. It all looked just right, but some random timeout appeared. But I'm telling you - I knew that it worked, as I used the feature before, so I kept retrying every once in a while. And it worked. That might help debug the issue. I also researched bugs in the upstream projects and found some vaguely related stuff, but from many years ago. 

> Sending the email should take less than a second.

Yeah, when it works it works in a second and makes you wonder what the fuss is about :)

As requested I tried again, but same result. My subject and body only consisted out of 3 characters so real small

`2022-02-20T10:59:17.712468+01:00 b3d7b3d95e0e postfix/smtpd[13439]: connect from mailu-admin-1.mailu_default[192.168.203.6]

2022-02-20T10:59:17.715164+01:00 b3d7b3d95e0e postfix/smtpd[13439]: discarding EHLO keywords: PIPELINING

INFO:root:Connect 

DEBUG:root:Received bytearray(b'transport *')

DEBUG:root:Request transport/*

_DEBUG:root:Table get *_

DEBUG:root:Replying b'NOTFOUND '

DEBUG:root:Received bytearray(b'transport *')

DEBUG:root:Request transport/*

DEBUG:root:Table get *

DEBUG:root:Replying b'NOTFOUND '

DEBUG:root:Received bytearray(b'domain example.com')

DEBUG:root:Request domain/example.com

DEBUG:root:Table get example.com

DEBUG:root:Table get example.com is example.com

DEBUG:root:Replying b'OK example.com'

DEBUG:root:Received bytearray(b'transport example.com')

DEBUG:root:Request transport/example.com

DEBUG:root:Table get example.com

DEBUG:root:Replying b'NOTFOUND '

DEBUG:root:Received bytearray(b'transport admin@example.com')

DEBUG:root:Request transport/admin@example.com

DEBUG:root:Table get admin@example.com

DEBUG:root:Replying b'NOTFOUND '

DEBUG:root:Received bytearray(b'transport *')

DEBUG:root:Request transport/*

DEBUG:root:Table get *

DEBUG:root:Replying b'NOTFOUND '

2022-02-20T10:59:49.216014+01:00 b3d7b3d95e0e postfix/smtpd[13439]: disconnect from mailu-admin-1.mailu_default[192.168.203.6] ehlo=1 mail=1 quit=1 commands=3`


The timeout (and so the wait after pressing send) occurs after the 5 line of this log (so after DEBUG:root:Table get *)
When that timeout has passed the 502 error is displayed (and the other lines logged)
I'm just a user myself FYI. And by trying again, I meant hammering it. I had my text on copy paste and tried at least two dozen times at varying hours. I have no clue how to debug this, I just said that in case someone needs to get something out urgently. I also checked the GH issues first when it happened to me and was lost, because the mailu team is overwhelmed already and no quick fix was in sight. I tried taking the containers down and up, taking other applications down temporarily to see if it was somehow exploding memory, but that made no difference. At random times it works fine.
At least mail itself worked continuously. Before the v1.8 I had a nasty bug that made me almost quit mailu (a minor update completely broke everything, and there was no way to go back one release) and it being understaffed meant all panic and no solution.

So if anyone finds this via search: hammer it. Or get all the mails via SQL from the `./data/main.db` and send normally via Thunderbird instead. Although I don't know how many mails at once TB/the stack can effectively handle, TB is a mess to begin with and wasn't meant for mass-mailing. If you do this a lot and have hundreds of users you might just want to make a little py script for now that sends them one after another.
Does the postmaster account exist?
The local part comes from POSTMASTER in mailu.env.
The domain part is from DOMAIN in mailu.env.

> Does the postmaster account exist? The local part comes from POSTMASTER in mailu.env. The domain part is from DOMAIN in mailu.env.

Yes it does. it is set to admin in mailu.env and that is also the account I log in with for sending this. I have even tried defining the alias of postmaster for this account, but also that does not resolve it unfortunately.
I did find out though that sending a welcome mail (setting it to through in mailu.env) also fails. And yet sending and receiving mail as a normal users works.... 

Like this:
  SUBNET=192.168.203.0/24
  DOMAIN=example.com
  HOSTNAMES=mail.example.com
  POSTMASTER=admin
  TLS_FLAVOR=letsencrypt

I do wonder if it might have to do with the /etc/postfix/master.cf file
Looking at the code it seems the smtp on port 10025 is being used.
Can someone determine if that is perhaps blocking it ? Regular smtp works fine

> bash-5.1# cat /etc/postfix/master.cf
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)

# Exposed SMTP service
smtp      inet  n       -       n       -       -       smtpd

# Internal SMTP service
10025     inet  n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_discard_ehlo_keywords=pipelining
  -o smtpd_client_restrictions=$check_ratelimit,reject_unlisted_sender,reject_authenticated_sender_login_mismatch,permit
  -o smtpd_reject_unlisted_recipient=no
  -o cleanup_service_name=outclean
outclean  unix n       -       n       -       0       cleanup
  -o header_checks=pcre:/etc/postfix/outclean_header_filter.cf
  -o nested_header_checks=
Some more detailed log from smtpd on port 10025 from the moment I try to send a public announcement you can find in the file here:

[detailed log.txt](https://github.com/Mailu/Mailu/files/8103785/detailed.log.txt)


> Does the postmaster account exist? The local part comes from POSTMASTER in mailu.env. The domain part is from DOMAIN in mailu.env.

Hi Dimitri,

Could you please have another look at this ? I provided a lot more detailed information ...


In a similar fashion, today I've ran into the much dreaded 'auth failed' bug from more than a year ago again.

It magically works again after a while, just like the announcements do for us, but this cannot be a permanent state.

As usual the logs show nothing useful:
```
front_1     | 2022/03/05 15:29:33 [error] 13#13: *590 recv() failed (111: Connection refused) while reading response from upstream, client: 1.2.3.4, server: 0.0.0.0:465, login: "foo@bar.com", upstream: 192.168.203.8:10025
front_1     | 2022/03/05 15:29:33 [crit] 13#13: *590 SSL_shutdown() failed (SSL: error:14094123:SSL routines:ssl3_read_bytes:application data after close notify) while reading response from upstream, client: 1.2.3.4, server: 0.0.0.0:465, login: "foo@bar.com", upstream: 192.168.203.8:10025
```

I'm posting in this thread because whatever causes this random behaviour must be linked. Last time the update to 1.8 fixed it. I hate seeing this yet again..

We need reliability, and as much as I like the simplicity of mailu compared to the rest, not being able to debug these issues in a timely fashion eventually will force my hand to move to something else. Please prioritize at least critical issues like 'random' behaviour.

For the record, this is v1.8. I will try updating and hope it fixes it again like last time..
Edit: It did just like last time. 'Last time' turns out was only half a year ago.
I confirm announcements don't work for me, too.
My setup is Mailu 1.9 / docker-compose / letsencrypt flavor / no overrides for now, and the issue is exactly the one described by @metlinux.
I don't know if it is related, I also get an error 502 when I use the admin web interface to create a new user, although in this case the user is effectively created, so it's not really a problem.
EDIT: it IS related, since the "welcome" message (set to true in mailu.env) never reaches the new user's box.
Issues not for bugs, enhancement requests or discussion go stale after 21 days of inactivity. This issue will be automatically closed after 14 days.
For all metrics refer to the [stale.yml file](https://github.com/Mailu/Mailu/blob/master/.github/stale.yml).
Github issues are not meant for user support. For **user-support questions**, reach out  on the [matrix support channel](https://matrix.to/#/#mailu:tedomum.net).

Mark the issue as fresh by simply adding a comment to the issue.
If this issue is safe to close, please do so now.

The message is rejected by rspamd with `forced: soft reject "Try again later"; score=nan (set by greylist)`
Maybe the private IP of the admin conatiner needs to be skipped in rspamd:
```
(default: F (soft reject): [11.40/15.00] [HFILTER_HELO_BADIP(4.50){192.168.203.6;1;},
VIOLATED_DIRECT_SPF(3.50){},MISSING_MID(2.50){},MISSING_DATE(1.00){},MIME_GOOD(-0.10){text/plain;},
ARC_NA(0.00){},ARC_SIGNED(0.00){xx.yy:s=dkim:i=1;},DMARC_NA(0.00){aa.bb;},FROM_EQ_ENVFROM(0.00){},
FROM_NO_DN(0.00){},GREYLIST(0.00){greylisted;Mon, 04 Apr 2022 09:24:05 GMT;new record;},
MIME_TRACE(0.00){0:+;},RCPT_COUNT_ONE(0.00){1;},RCVD_COUNT_ZERO(0.00){0;},R_DKIM_NA(0.00){},
R_SPF_SOFTFAIL(0.00){~all:c;},TO_DN_NONE(0.00){},TO_MATCH_ENVRCPT_ALL(0.00){}])
```
The second part of the problem is not handling smtplib exceptions (smtplib.SMTPDataError) in models.py (line 425):
```
smtp.sendmail(f_addr, [to_address], msg.as_string())
=> smtplib.SMTPDataError: (451, b'4.7.1 Try again later')
```

What is odd, is that the SUBNET (192.168.203.0/24) setting (from mailu.env) should have been configured as ``local_networks = [192.168.203.0/24];`` in options.inc of rspamd. 
This results in it being added as local_addrs in the rspamd config.

[This setting](https://rspamd.com/doc/configuration/options.html) configures; ``map or list of IP networks used as local, so certain checks are skipped for them (e.g. SPF checks)``.
Yet in the log excerpt we see that SPF check does take place. Rspamd ignores the setting? Or perhaps the subnet is incorrectly configured? SUBNET in mailu.env should match the subnet configured in docker-compose.yml.

If SUBNET in mailu.env matches the subnet in  the docker-compose.yml file, then it should not be  rejected. No SPF test takes place.

The settings of rspamd can be checked by first going into a shell and then running rspamadm configdump:
```
docker-compose exec antispam bash
rspamadm configdump | less
/options
```
In the options you should see the local_addr section with the whitelisted ips
```
options {
    check_all_filters = true;
...
    local_addrs [
        "192.168.0.0/16",
        "10.0.0.0/8",
        "172.16.0.0/12",
        "fd00::/8",
        "169.254.0.0/16",
        "fe80::/10",
        "127.2.4.7",
    ]
```

 "192.168.0.0/16", is my SUBNET setting.

As a test, 
1. I added google.com as domain in the Admin WebUI.
2.  Added an administrator user for the domain google.com. 
3. Changed DOMAIN in mailu.env to google.com. (DOMAIN is used as sender for sending public announcements). 
4. Send a public announcement. If SPF is checked, then rspamd will not allow this.
5. Result, email is send.
```
rspamd_task_write_log: id: <undef>, qid: <9CFC9C0414>, ip: 192.168.203.7, from: <admin@google.com>, (default: F (no action): [3.40/15.00] [MISSING_MID(2.50){},MISSING_DATE(1.00){},MIME_GOOD(-0.10){text/plain;},ARC_NA(0.00){},FROM_EQ_ENVFROM(0.00){},FROM_NO_DN(0.00){},MIME_TRACE(0.00){0:+;},RCPT_COUNT_ONE(0.00){1;},RCVD_COUNT_ZERO(0.00){0;},TO_DN_NONE(0.00){},TO_MATCH_ENVRCPT_ALL(0.00){}]), len: 253, time: 63.330ms, dns req: 1, digest: <22bfa85cfd7bdb692033454ae2b44ddb>, rcpts: <admin@somedomain.com>, mime_rcpts: <admin@somedomain.com>
proxy; rspamd_protocol_http_reply: regexp statistics: 41 pcre regexps scanned, 0 regexps matched, 172 regexps total, 11 regexps cached, 1.03KiB scanned using pcre, 1.03KiB scanned total
proxy; proxy_milter_finish_handler: finished milter connection
proxy; proxy_accept_socket: accepted milter connection from 192.168.203.9 port 54560
milter; rspamd_milter_process_command: got connection from 192.168.203.7:33374
proxy; rspamd_message_parse: loaded message; id: <undef>; queue-id: <D17B5C0451>; size: 253; checksum: <22bfa85cfd7bdb692033454ae2b44ddb>
proxy; rspamd_mime_part_detect_language: detected part language: vi
lua; greylist.lua:217: skip greylisting for local networks and/or authorized users
proxy; dkim_symbol_callback: skip DKIM checks for local networks and authorized users
lua; spf.lua:186: skip SPF checks for local networks and authorized users
lua; dmarc.lua:349: skip DMARC checks as either SPF or DKIM were not checked
lua; once_received.lua:99: Skipping once_received for authenticated user or local network
proxy; rspamd_redis_connected: skip obtaining bayes tokens for BAYES_HAM of classifier bayes: not enough learns 0; 200 required
proxy; rspamd_redis_connected: skip obtaining bayes tokens for BAYES_SPAM of classifier bayes: not enough learns 33; 200 required
proxy; rspamd_stat_classifiers_process: skip statistics as SPAM class is missing
lua; greylist.lua:331: Score too low - skip greylisting
```

Note the:
```
lua; spf.lua:186: skip SPF checks for local networks and authorized users
lua; dmarc.lua:349: skip DMARC checks as either SPF or DKIM were not checked
lua; once_received.lua:99: Skipping once_received for authenticated user or local network
```
IMHO we should do LMTP delivery to the inboxes here, not fuss around with the filters.

Resolving patch:
diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py
--- a/core/admin/mailu/models.py
+++ b/core/admin/mailu/models.py
@@ -2,7 +2,6 @@
 """
 
 import os
-import smtplib
 import json
 
 from datetime import date
@@ -412,14 +411,19 @@ def __declare_last__(cls):
 
     def sendmail(self, subject, body):
         """ send an email to the address """
-        f_addr = f'{app.config["POSTMASTER"]}@{idna.encode(app.config["DOMAIN"]).decode("ascii")}'
-        with smtplib.SMTP(app.config['HOST_AUTHSMTP'], port=10025) as smtp:
-            to_address = f'{self.localpart}@{idna.encode(self.domain_name).decode("ascii")}'
-            msg = text.MIMEText(body)
-            msg['Subject'] = subject
-            msg['From'] = f_addr
-            msg['To'] = to_address
-            smtp.sendmail(f_addr, [to_address], msg.as_string())
+        try:
+            f_addr = f'{app.config["POSTMASTER"]}@{idna.encode(app.config["DOMAIN"]).decode("ascii")}'
+            ip, port = app.config['HOST_LMTP'].rsplit(':')
+            with smtplib.LMTP(ip, port=port) as lmtp:
+                to_address = f'{self.localpart}@{idna.encode(self.domain_name).decode("ascii")}'
+                msg = text.MIMEText(body)
+                msg['Subject'] = subject
+                msg['From'] = f_addr
+                msg['To'] = to_address
+                lmtp.sendmail(f_addr, [to_address], msg.as_string())
+            return True
+        except smtplib.SMTPException:
+            return False
 
     @classmethod
     def resolve_domain(cls, email):
diff --git a/core/admin/mailu/ui/views/base.py b/core/admin/mailu/ui/views/base.py
--- a/core/admin/mailu/ui/views/base.py
+++ b/core/admin/mailu/ui/views/base.py
@@ -21,8 +21,9 @@ def announcement():
     form = forms.AnnouncementForm()
     if form.validate_on_submit():
         for user in models.User.query.all():
-            user.sendmail(form.announcement_subject.data,
-                form.announcement_body.data)
+            if not user.sendmail(form.announcement_subject.data,
+                    form.announcement_body.data):
+                flask.flash('Failed to send to %s' % user.email, 'error')
         # Force-empty the form
         form.announcement_subject.data = ''
         form.announcement_body.data = ''


Test patch: