Skip to content

Commit fc037b4

Browse files
KN4CK3Rsilverwindlunny
authored
Add support for incoming emails (#22056)
closes #13585 fixes #9067 fixes #2386 ref #6226 ref #6219 fixes #745 This PR adds support to process incoming emails to perform actions. Currently I added handling of replies and unsubscribing from issues/pulls. In contrast to #13585 the IMAP IDLE command is used instead of polling which results (in my opinion 😉) in cleaner code. Procedure: - When sending an issue/pull reply email, a token is generated which is present in the Reply-To and References header. - IMAP IDLE waits until a new email arrives - The token tells which action should be performed A possible signature and/or reply gets stripped from the content. I added a new service to the drone pipeline to test the receiving of incoming mails. If we keep this in, we may test our outgoing emails too in future. Co-authored-by: silverwind <[email protected]> Co-authored-by: Lunny Xiao <[email protected]>
1 parent 20e3ffd commit fc037b4

26 files changed

+1525
-39
lines changed

.drone.yml

+4
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ services:
230230
MINIO_ACCESS_KEY: 123456
231231
MINIO_SECRET_KEY: 12345678
232232

233+
- name: smtpimap
234+
image: tabascoterrier/docker-imap-devel:latest
235+
pull: always
236+
233237
steps:
234238
- name: fetch-tags
235239
image: docker:git

assets/go-licenses.json

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

custom/conf/app.example.ini

+41
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,47 @@ ROUTER = console
16641664
;; convert \r\n to \n for Sendmail
16651665
;SENDMAIL_CONVERT_CRLF = true
16661666

1667+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1668+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1669+
;[email.incoming]
1670+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1671+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1672+
;;
1673+
;; Enable handling of incoming emails.
1674+
;ENABLED = false
1675+
;;
1676+
;; The email address including the %{token} placeholder that will be replaced per user/action.
1677+
;; Example: incoming+%{token}@example.com
1678+
;; The placeholder must appear in the user part of the address (before the @).
1679+
;REPLY_TO_ADDRESS =
1680+
;;
1681+
;; IMAP server host
1682+
;HOST =
1683+
;;
1684+
;; IMAP server port
1685+
;PORT =
1686+
;;
1687+
;; Username of the receiving account
1688+
;USERNAME =
1689+
;;
1690+
;; Password of the receiving account
1691+
;PASSWORD =
1692+
;;
1693+
;; Whether the IMAP server uses TLS.
1694+
;USE_TLS = false
1695+
;;
1696+
;; If set to true, completely ignores server certificate validation errors. This option is unsafe.
1697+
;SKIP_TLS_VERIFY = true
1698+
;;
1699+
;; The mailbox name where incoming mail will end up.
1700+
;MAILBOX = INBOX
1701+
;;
1702+
;; Whether handled messages should be deleted from the mailbox.
1703+
;DELETE_HANDLED_MESSAGE = true
1704+
;;
1705+
;; Maximum size of a message to handle. Bigger messages are ignored. Set to 0 to allow every size.
1706+
;MAXIMUM_MESSAGE_SIZE = 10485760
1707+
16671708
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16681709
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16691710
;[cache]

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+14
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,20 @@ and
750750
- `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
751751
- `SEND_AS_PLAIN_TEXT`: **false**: Send mails only in plain text, without HTML alternative.
752752

753+
## Incoming Email (`email.incoming`)
754+
755+
- `ENABLED`: **false**: Enable handling of incoming emails.
756+
- `REPLY_TO_ADDRESS`: **\<empty\>**: The email address including the `%{token}` placeholder that will be replaced per user/action. Example: `incoming+%{token}@example.com`. The placeholder must appear in the user part of the address (before the `@`).
757+
- `HOST`: **\<empty\>**: IMAP server host.
758+
- `PORT`: **\<empty\>**: IMAP server port.
759+
- `USERNAME`: **\<empty\>**: Username of the receiving account.
760+
- `PASSWORD`: **\<empty\>**: Password of the receiving account.
761+
- `USE_TLS`: **false**: Whether the IMAP server uses TLS.
762+
- `SKIP_TLS_VERIFY`: **false**: If set to `true`, completely ignores server certificate validation errors. This option is unsafe.
763+
- `MAILBOX`: **INBOX**: The mailbox name where incoming mail will end up.
764+
- `DELETE_HANDLED_MESSAGE`: **true**: Whether handled messages should be deleted from the mailbox.
765+
- `MAXIMUM_MESSAGE_SIZE`: **10485760**: Maximum size of a message to handle. Bigger messages are ignored. Set to 0 to allow every size.
766+
753767
## Cache (`cache`)
754768

755769
- `ENABLED`: **true**: Enable the cache.

docs/content/doc/features/comparison.en-us.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ _Symbols used in table:_
106106
| Issue search ||||||||
107107
| Global issue search | [/](https://github.com/go-gitea/gitea/issues/2434) |||||||
108108
| Issue dependency ||||||||
109-
| Create issue via email | [](https://github.com/go-gitea/gitea/issues/6226) ||| ||||
109+
| Create issue via email | [](https://github.com/go-gitea/gitea/issues/6226) ||| ||||
110110
| Service Desk | [](https://github.com/go-gitea/gitea/issues/6219) |||||||
111111

112112
## Pull/Merge requests

docs/content/doc/features/comparison.zh-cn.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ _表格中的符号含义:_
9292
| 工单搜索 ||||||||
9393
| 工单全局搜索 | [](https://github.com/go-gitea/gitea/issues/2434) |||||||
9494
| 工单依赖关系 ||||||||
95-
| 通过 Email 创建工单 | [](https://github.com/go-gitea/gitea/issues/6226) | [](https://github.com/gogs/gogs/issues/2602) || ||||
95+
| 通过 Email 创建工单 | [](https://github.com/go-gitea/gitea/issues/6226) | [](https://github.com/gogs/gogs/issues/2602) || ||||
9696
| 服务台 | [](https://github.com/go-gitea/gitea/issues/6219) ||| [](https://gitlab.com/groups/gitlab-org/-/epics/3103) ||||
9797

9898
#### Pull/Merge requests

docs/content/doc/features/comparison.zh-tw.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ menu:
9393
| 問題搜尋 ||||||||
9494
| 全域問題搜尋 | [](https://github.com/go-gitea/gitea/issues/2434) |||||||
9595
| 問題相依 ||||||||
96-
| 從電子郵件建立問題 | [](https://github.com/go-gitea/gitea/issues/6226) | [](https://github.com/gogs/gogs/issues/2602) || ||||
96+
| 從電子郵件建立問題 | [](https://github.com/go-gitea/gitea/issues/6226) | [](https://github.com/gogs/gogs/issues/2602) || ||||
9797
| 服務台 | [](https://github.com/go-gitea/gitea/issues/6219) ||| [](https://gitlab.com/groups/gitlab-org/-/epics/3103) ||||
9898

9999
## 拉取/合併請求
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
date: "2022-12-01T00:00:00+00:00"
3+
title: "Incoming Email"
4+
slug: "incoming-email"
5+
draft: false
6+
toc: false
7+
menu:
8+
sidebar:
9+
parent: "usage"
10+
name: "Incoming Email"
11+
weight: 13
12+
identifier: "incoming-email"
13+
---
14+
15+
# Incoming Email
16+
17+
Gitea supports the execution of several actions through incoming mails. This page describes how to set this up.
18+
19+
**Table of Contents**
20+
21+
{{< toc >}}
22+
23+
## Requirements
24+
25+
Handling incoming email messages requires an IMAP-enabled email account.
26+
The recommended strategy is to use [email sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing) but a catch-all mailbox does work too.
27+
The receiving email address contains a user/action specific token which tells Gitea which action should be performed.
28+
This token is expected in the `To` and `Delivered-To` header fields.
29+
30+
Gitea tries to detect automatic responses to skip and the email server should be configured to reduce the incoming noise too (spam, newsletter).
31+
32+
## Configuration
33+
34+
To activate the handling of incoming email messages you have to configure the `email.incoming` section in the configuration file.
35+
36+
The `REPLY_TO_ADDRESS` contains the address an email client will respond to.
37+
This address needs to contain the `%{token}` placeholder which will be replaced with a token describing the user/action.
38+
This placeholder must only appear once in the address and must be in the user part of the address (before the `@`).
39+
40+
An example using email sub-addressing may look like this: `incoming+%{token}@example.com`
41+
42+
If a catch-all mailbox is used, the placeholder may be used anywhere in the user part of the address: `incoming+%{token}@example.com`, `incoming_%{token}@example.com`, `%{token}@example.com`
43+
44+
## Security
45+
46+
Be careful when choosing the domain used for receiving incoming email.
47+
It's recommended receiving incoming email on a subdomain, such as `incoming.example.com` to prevent potential security problems with other services running on `example.com`.

go.mod

+6-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ require (
2020
github.com/buildkite/terminal-to-html/v3 v3.7.0
2121
github.com/caddyserver/certmagic v0.17.2
2222
github.com/chi-middleware/proxy v1.1.1
23-
github.com/denisenkom/go-mssqldb v0.12.3
23+
github.com/denisenkom/go-mssqldb v0.12.2
24+
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
2425
github.com/djherbis/buffer v1.2.0
2526
github.com/djherbis/nio/v3 v3.0.1
2627
github.com/dustin/go-humanize v1.0.0
2728
github.com/editorconfig/editorconfig-core-go/v2 v2.5.1
29+
github.com/emersion/go-imap v1.2.1
2830
github.com/emirpasic/gods v1.18.1
2931
github.com/ethantkoenig/rupture v1.0.1
3032
github.com/felixge/fgprof v0.9.3
@@ -58,6 +60,7 @@ require (
5860
github.com/hashicorp/golang-lru v0.6.0
5961
github.com/huandu/xstrings v1.4.0
6062
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba
63+
github.com/jhillyerd/enmime v0.10.1
6164
github.com/json-iterator/go v1.1.12
6265
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
6366
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
@@ -145,6 +148,7 @@ require (
145148
github.com/blevesearch/zapx/v15 v15.3.8 // indirect
146149
github.com/boombuler/barcode v1.0.1 // indirect
147150
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
151+
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
148152
github.com/cespare/xxhash/v2 v2.1.2 // indirect
149153
github.com/cloudflare/circl v1.2.0 // indirect
150154
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
@@ -155,6 +159,7 @@ require (
155159
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
156160
github.com/dlclark/regexp2 v1.7.0 // indirect
157161
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
162+
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
158163
github.com/felixge/httpsnoop v1.0.3 // indirect
159164
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
160165
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea // indirect

0 commit comments

Comments
 (0)