Repository: matrix-org/synapse

Issue:
Allow setting e-mail headers in configuration file
Setting email headers like `X-Auto-Response-Suppress` can be very useful when enabling email notifications, as you may be flooded with auto-responses from absent employees etc.

Using a noreply email address can be an alternative in some cases, but not all (for us this is not an option).

I can imagine this is a minor fix. Either, if it's only this one header, put a boolean flag in the `email` configuration part which, if set, makes synapse add the header to all sent emails. Or, if multiple headers are interesting, allow some yaml-list-like structure where admins can set custom headers as needed.

Especially the first option is probably a very minor fix, but would have great impact on our use of synapse.


Discussion:
For reference, X-Auto-Response-Suppress seems to be something to do with Exchange: see https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmail/ced68690-498a-4567-9d14-5c01f974d8b1

I think we'd probably accept a PR which adds a config option that lets you specify arbitrary headers. 

Something like:

```yaml
email:
  outgoing_headers:
      X-Auto-Response-Suppress: "OOF"
      X-Something-Else: "Potato"
```

Rough implementation plan:

1. Define new config format in the config manual. Include which version of Synapse this would be added in.
2. Parse new config from yaml in `emailconfig.py`.
3. Read that config in `send_email.py` and apply it to the headers here:
    https://github.com/matrix-org/synapse/blob/e8519e0ed289b67fa07c1bdbb6898852dc1a50b9/synapse/handlers/send_email.py#L184-L189
4. Write a short test case in `test_email.py` which proves your config is read and sent out as a header.

> I think we'd probably accept a PR which adds a config option that lets you specify arbitrary headers.

If there's no downside to including this header, maybe we should just include it? I'd prefer less config, if possible, and just use good defaults.
That's fair. I was thinking of not wanting to block further "can we also send this header?" requests on implementation work.

It looks like `X-Auto-Response-Suppress: All` is what we need? That's easy enough to do, I may as well just PR it now.

Resolving patch:
diff --git a/synapse/handlers/send_email.py b/synapse/handlers/send_email.py
--- a/synapse/handlers/send_email.py
+++ b/synapse/handlers/send_email.py
@@ -187,6 +187,19 @@ async def send_email(
         multipart_msg["To"] = email_address
         multipart_msg["Date"] = email.utils.formatdate()
         multipart_msg["Message-ID"] = email.utils.make_msgid()
+        # Discourage automatic responses to Synapse's emails.
+        # Per RFC 3834, automatic responses should not be sent if the "Auto-Submitted"
+        # header is present with any value other than "no". See
+        #     https://www.rfc-editor.org/rfc/rfc3834.html#section-5.1
+        multipart_msg["Auto-Submitted"] = "auto-generated"
+        # Also include a Microsoft-Exchange specific header:
+        #    https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmail/ced68690-498a-4567-9d14-5c01f974d8b1
+        # which suggests it can take the value "All" to "suppress all auto-replies",
+        # or a comma separated list of auto-reply classes to suppress.
+        # The following stack overflow question has a little more context:
+        #    https://stackoverflow.com/a/25324691/5252017
+        #    https://stackoverflow.com/a/61646381/5252017
+        multipart_msg["X-Auto-Response-Suppress"] = "All"
         multipart_msg.attach(text_part)
         multipart_msg.attach(html_part)
 


Test patch: