bugfixes; email parsing; send emails into matrix rooms; e2e tests

This commit is contained in:
Aine
2022-08-22 12:28:29 +03:00
parent c746c91dbb
commit e6d5e81efe
16 changed files with 428 additions and 24 deletions

View File

@@ -4,11 +4,13 @@ An Email to Matrix bridge
## Features / Roadmap / TODO ## Features / Roadmap / TODO
- [ ] **BUG**: no auto invites
- [x] SMTP server - [x] SMTP server
- [ ] SMTP client - [ ] SMTP client
- [x] Matrix bot - [x] Matrix bot
- [x] Configuration in room's account data - [x] Configuration in room's account data
- [ ] Receive emails to matrix rooms - [x] Receive emails to matrix rooms
- [ ] Receive attachments
- [ ] Map email threads to matrix threads - [ ] Map email threads to matrix threads
- [ ] Reply to matrix thread sends reply into email thread - [ ] Reply to matrix thread sends reply into email thread
- [ ] Send a message to matrix room with special format to send a new email - [ ] Send a message to matrix room with special format to send a new email
@@ -34,3 +36,14 @@ env vars
* **POSTMOOGLE_DB_DIALECT** - database dialect (postgres, sqlite3) * **POSTMOOGLE_DB_DIALECT** - database dialect (postgres, sqlite3)
You can find default values in [config/defaults.go](config/defaults.go) You can find default values in [config/defaults.go](config/defaults.go)
## Development
### Prerequisites
* [ssmtp](https://wiki.archlinux.org/title/SSMTP)
* configured mailbox `test@localhost`
### Testing
Run `send` script of the `e2e` dir with example emails

View File

@@ -10,6 +10,7 @@ import (
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
"gitlab.com/etke.cc/go/logger" "gitlab.com/etke.cc/go/logger"
"gitlab.com/etke.cc/linkpearl" "gitlab.com/etke.cc/linkpearl"
"gitlab.com/etke.cc/postmoogle/utils"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format" "maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id" "maunium.net/go/mautrix/id"
@@ -28,10 +29,11 @@ type Bot struct {
// New creates a new matrix bot // New creates a new matrix bot
func New(lp *linkpearl.Linkpearl, log *logger.Logger, prefix, domain string) *Bot { func New(lp *linkpearl.Linkpearl, log *logger.Logger, prefix, domain string) *Bot {
return &Bot{ return &Bot{
prefix: prefix, roomsmu: &sync.Mutex{},
domain: domain, prefix: prefix,
log: log, domain: domain,
lp: lp, log: log,
lp: lp,
} }
} }
@@ -73,7 +75,7 @@ func (b *Bot) Start() error {
// Send email to matrix room // Send email to matrix room
func (b *Bot) Send(from, to, subject, body string) error { func (b *Bot) Send(from, to, subject, body string) error {
roomID, ok := b.rooms[to] roomID, ok := b.rooms[utils.Mailbox(to)]
if !ok || roomID == "" { if !ok || roomID == "" {
return errors.New("room not found") return errors.New("room not found")
} }

View File

@@ -33,7 +33,7 @@ func (b *Bot) parseCommand(message string) []string {
return nil return nil
} }
message = strings.Replace(message, b.prefix+" ", "", 1) message = strings.TrimSpace(strings.Replace(message, b.prefix, "", 1))
return strings.Split(message, " ") return strings.Split(message, " ")
} }

View File

@@ -58,5 +58,6 @@ func (b *Bot) getSettings(ctx context.Context, roomID id.RoomID) (*settings, err
func (b *Bot) setSettings(ctx context.Context, roomID id.RoomID, cfg *settings) error { func (b *Bot) setSettings(ctx context.Context, roomID id.RoomID, cfg *settings) error {
span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setSettings")) span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setSettings"))
defer span.Finish() defer span.Finish()
return b.lp.GetClient().SetRoomAccountData(roomID, settingskey, cfg) return b.lp.GetClient().SetRoomAccountData(roomID, settingskey, cfg)
} }

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
"gitlab.com/etke.cc/postmoogle/utils"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format" "maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id" "maunium.net/go/mautrix/id"
@@ -23,7 +24,7 @@ func (b *Bot) syncRooms(ctx context.Context) error {
for _, roomID := range resp.JoinedRooms { for _, roomID := range resp.JoinedRooms {
cfg, serr := b.getSettings(span.Context(), roomID) cfg, serr := b.getSettings(span.Context(), roomID)
if serr != nil { if serr != nil {
b.Error(span.Context(), roomID, "cannot get room settings: %v", err) b.log.Warn("cannot get %s settings: %v", roomID, err)
continue continue
} }
if cfg.Mailbox != "" { if cfg.Mailbox != "" {
@@ -48,8 +49,7 @@ func (b *Bot) getMailbox(ctx context.Context, evt *event.Event) {
cfg, err := b.getSettings(span.Context(), evt.RoomID) cfg, err := b.getSettings(span.Context(), evt.RoomID)
if err != nil || cfg == nil { if err != nil || cfg == nil {
b.Error(span.Context(), evt.RoomID, "cannot get settings: %v", err) b.log.Warn("cannot get %s settings: %v", evt.RoomID, err)
return
} }
if cfg.Mailbox == "" { if cfg.Mailbox == "" {
@@ -69,6 +69,7 @@ func (b *Bot) setMailbox(ctx context.Context, evt *event.Event, mailbox string)
span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setMailbox")) span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setMailbox"))
defer span.Finish() defer span.Finish()
mailbox = utils.Mailbox(mailbox)
existingID, ok := b.rooms[mailbox] existingID, ok := b.rooms[mailbox]
if ok && existingID != "" && existingID != evt.RoomID { if ok && existingID != "" && existingID != evt.RoomID {
content := format.RenderMarkdown("Mailbox "+mailbox+"@"+b.domain+" already taken", true, true) content := format.RenderMarkdown("Mailbox "+mailbox+"@"+b.domain+" already taken", true, true)

View File

@@ -6,7 +6,7 @@ var defaultConfig = &Config{
Port: "25", Port: "25",
Prefix: "!pm", Prefix: "!pm",
DB: DB{ DB: DB{
DSN: "/tmp/postmoogle.db", DSN: "local.db",
Dialect: "sqlite3", Dialect: "sqlite3",
}, },
Sentry: Sentry{ Sentry: Sentry{

3
e2e/send Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
ssmtp -v test@localhost < $1

54
e2e/simple.eml Normal file
View File

@@ -0,0 +1,54 @@
From: James Hillyerd <james@makita.skynet>
Content-Type: multipart/alternative; boundary="Apple-Mail=_E091454E-BCFA-43B4-99C0-678AEC9868D6"
Subject: MIME test 1
Date: Sat, 13 Oct 2012 15:33:07 -0700
Message-Id: <4E2E5A48-1A2C-4450-8663-D41B451DA93E@makita.skynet>
To: test@localhost
Mime-Version: 1.0 (Apple Message framework v1283)
X-Mailer: Apple Mail (2.1283)
--Apple-Mail=_E091454E-BCFA-43B4-99C0-678AEC9868D6
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=us-ascii
Test of text section
--Apple-Mail=_E091454E-BCFA-43B4-99C0-678AEC9868D6
Content-Type: multipart/related;
type="text/html";
boundary="Apple-Mail=_D2ABE25A-F0FE-404E-94EE-D98BD23448D5"
--Apple-Mail=_D2ABE25A-F0FE-404E-94EE-D98BD23448D5
Content-Transfer-Encoding: 7bit
Content-Type: text/html;
charset=us-ascii
<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><font class="Apple-style-span" face="'Comic Sans MS'">Test of HTML section</font><img height="16" width="16" apple-width="yes" apple-height="yes" id="4579722f-d53d-45d0-88bc-f8209a2ca569" src="cid:8B8481A2-25CA-4886-9B5A-8EB9115DD064@skynet"></body></html>
--Apple-Mail=_D2ABE25A-F0FE-404E-94EE-D98BD23448D5
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename=favicon.png
Content-Type: image/png;
x-unix-mode=0644;
name="favicon.png"
Content-Id: <8B8481A2-25CA-4886-9B5A-8EB9115DD064@skynet>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
bWFnZVJlYWR5ccllPAAAAlFJREFUeNqUU8tOFEEUPVVdNV3dPe8xYRBnjGhmBgKjKzCIiQvBoIaN
bly5Z+PSv3Aj7DSiP2B0rwkLGVdGgxITSCRIJGSMEQWZR3eVt5sEFBgTb/dN1yvnnHtPNTPG4Pqd
HgCMXnPRSZrpSuH8vUJu4DE4rYHDGAZDX62BZttHqTiIayM3gGiXQsgYLEvATaqxU+dy1U13YXap
XptpNHY8iwn8KyIAzm1KBdtRZWErpI5lEWTXp5Z/vHpZ3/wyKKwYGGOdAYwR0EZwoezTYApBEIOb
yELl/aE1/83cp40Pt5mxqCKrE4Ck+mVWKKcI5tA8BLEhRBKJLjez6a7MLq7XZtp+yyOawwCBtkiB
VZDKzRk4NN7NQBMYPHiZDFhXY+p9ff7F961vVcnl4R5I2ykJ5XFN7Ab7Gc61VoipNBKF+PDyztu5
lfrSLT/wIwCxq0CAGtXHZTzqR2jtwQiXONma6hHpj9sLT7YaPxfTXuZdBGA02Wi7FS48YiTfj+i2
NhqtdhP5RC8mh2/Op7y0v6eAcWVLFT8D7kWX5S9mepp+C450MV6aWL1cGnvkxbwHtLW2B9AOkLeU
d9KEDuh9fl/7CEj7YH5g+3r/lWfF9In7tPz6T4IIwBJOr1SJyIGQMZQbsh5P9uBq5VJtqHh2mo49
pdw5WFoEwKWqWHacaWOjQXWGcifKo6vj5RGS6zykI587XeUIQDqJSmAp+lE4qt19W5P9o8+Lma5D
cjsC8JiT607lMVkdqQ0Vyh3lHhmh52tfNy78ajXv0rgYzv8nfwswANuk+7sD/Q0aAAAAAElFTkSu
QmCC
--Apple-Mail=_D2ABE25A-F0FE-404E-94EE-D98BD23448D5--
--Apple-Mail=_E091454E-BCFA-43B4-99C0-678AEC9868D6--

268
e2e/uptimerobot.eml Normal file
View File

@@ -0,0 +1,268 @@
Return-Path: <alert@uptimerobot.com>
Delivered-To: test@localhost
Received: from mp12.migadu.com ([2001:41d0:8:6d80::])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
by ms2.migadu.com with LMTPS
id AFCBC0JA/2IjvAAAThjiIw
(envelope-from <alert@uptimerobot.com>)
for <test@localhost>; Fri, 19 Aug 2022 09:48:18 +0200
Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
by mp12.migadu.com with LMTPS
id AGRUC0JA/2KpWQAAauVa8A
(envelope-from <alert@uptimerobot.com>)
for <test@localhost>; Fri, 19 Aug 2022 09:48:18 +0200
Received: from mail2.uptimerobot.com (mail2.uptimerobot.com [216.144.250.150])
(using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by aspmx1.migadu.com (Postfix) with ESMTPS id 892E821C17
for <test@localhost>; Fri, 19 Aug 2022 09:48:17 +0200 (CEST)
dkim-signature:v=1; c=relaxed/relaxed; h=content-type:from:to:subject:message-id:content-transfer-encoding:date:mime-version;
d=uptimerobot.com; s=mail2; a=rsa-sha256;
bh=wgbGkwTvf0iMf6GWyq4eRri7/0akAM3yIzjn52Vvm6M=;
b=oeLExxHN3oEy4uoeSTxwDqFfC/xKOCtY7AY1OKR9P3AoV3Pw+iu8rNeAjDh9ySL5p
FibtVl9XjOyECSQpumHo27sqVaR0IO/bqBxlJRxfBw07gA/q1JmlDtryQeaV1vM3s7p
t2Rs2fdYdw2s2RYBEjP+6SqtL6vUq1rUSB+4YRtLk1cuiXIjDa3vYuuT2NioIxEo2dk
oUuvPW8jRXdE2gnmdUSZ42Hy8uX7Wr9ScAo8j/xNiFTWDPqD/u9IpHMDuVlKDfWhEgm
1YoT9ZDcJJ13JZN29ugY4u1tV+vu8k3NfLnPptqUif0S+b0lIPKTcu1af4nvZmjdEFZ
rbt3Rn4Og==;
Received: from [127.0.0.1] ([52.70.84.165]) by uptimerobot.com with
MailEnable ESMTPA; Fri, 19 Aug 2022 07:48:20 +0000
Content-Type: text/html; charset=utf-8
From: UptimeRobot <alert@uptimerobot.com>
To: test@localhost
Subject: Monitor is UP: Buscarron
Message-ID: <1660895293792.132971@uptimerobot.com>
Content-Transfer-Encoding: quoted-printable
Date: Fri, 19 Aug 2022 07:48:13 +0000
MIME-Version: 1.0
X-Migadu-Flow: FLOW_IN
X-Migadu-To: test@localhost
X-Migadu-Country: US
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=etke.cc;
s=key1; t=1660895298;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:dkim-signature;
bh=wgbGkwTvf0iMf6GWyq4eRri7/0akAM3yIzjn52Vvm6M=;
b=e6P3Be4Nf/cfOFkwt4r94xgp1JzsnT8WANfGuRU7VOfioRm6VHzpYOFJWlFXqwhxspk2lo
m6GaPjyQtJrSiYkcQWtUb9K/K2Y6r7JEb9IziyIvqzKQ2l/K5OPwX/nA2mDKYuTe4PR2/V
/Ec/zBKosuHKuBsyw35mFLF3uLJHyddpuYRdLhIM6qeksXC4bXQek1UtWSQ/P11MwFZ5DM
bSKU20djOMjYu0qE7xXa7/Zj78SnL08VKFLjo5OAboeDZZYfpdMh5Z0YWGPt4QkZWi9AON
fa49qfUYJwai1RVxKpuNhync6KjKv+8ceSgw+8ySwz85xwyKSIae9ZZ8NekouA==
ARC-Seal: i=1; s=key1; d=etke.cc; t=1660895298; a=rsa-sha256; cv=none;
b=FgLD30AkdygNHpzdD9OdIjqeCDr/dOxB0bsn8zk9Et5Ips1OmxbZIAs/bK71BAc3vefpnk
kxm63eFhABQZoI8TjoOtwE2lW2wOSmaoovFxUOqCSh7RO2mXD3wLX9OGeqbP+cTNdaYTab
lkClWxCQ2+mRABQw7YPHVt81IVcC2FzOBx8IXIlJrHTJ7C9J+yLRXIXqoZ0un0n6msASnh
q7nsXWc+U6M8aGTPHUVm5ur3muqIIaLBSHkDHfCjIAAxOObw0P01VhpjE4EiWM8d9hch7+
f8efT+7d/BwnIQy4C5gnhyAMtzaFN52MDlFtGAo/1Vba9yuByaf+1f8umwChSg==
ARC-Authentication-Results: i=1;
aspmx1.migadu.com;
dkim=pass header.d=uptimerobot.com header.s=mail2 header.b=oeLExxHN;
dmarc=pass (policy=quarantine) header.from=uptimerobot.com;
spf=pass (aspmx1.migadu.com: domain of alert@uptimerobot.com designates 216.144.250.150 as permitted sender) smtp.mailfrom=alert@uptimerobot.com
X-Migadu-Spam-Score: -7.21
Authentication-Results: aspmx1.migadu.com;
dkim=pass header.d=uptimerobot.com header.s=mail2 header.b=oeLExxHN;
dmarc=pass (policy=quarantine) header.from=uptimerobot.com;
spf=pass (aspmx1.migadu.com: domain of alert@uptimerobot.com designates 216.144.250.150 as permitted sender) smtp.mailfrom=alert@uptimerobot.com
X-Migadu-Queue-Id: 892E821C17
X-Spam-Score: -7.21
X-Migadu-Scanner: scn0.migadu.com
<html>
<head>
<meta name=3D"viewport" =
content=3D"width=3Ddevice-width">
<meta http-equiv=3D"Content-Typ=
e" content=3D"text/html; charset=3DUTF-8">
<title>Monitor is UP =
: Buscarron
</title>
</head>
<body style=3D"font-family: =
'Roboto', Arial, sans-serif; color: #131a26; background: #fefefe; =
line-height: 1.3em;">
<div style=3D"font-family: 'Roboto', Arial, =
sans-serif; color: #131a26; background: #fefefe; box-sizing: border-box; =
line-height: 1.3em;">
<div style=3D"background: #131a26; padding: =
45px 15px;">
<div style=3D"max-width: 600px; margin: 0 auto;">
<table style=3D" width: 100%; font-size: 14px; color: #ffffff;"=
width=3D"100%">
<tbody style=3D"">
<tr =
style=3D"">
<td width=3D"180" style=3D" font-size: =
36px;">
<a href=3D"https://uptimerobot.com/dashboard?=
utm_source=3DalertMessage&utm_medium=3Demail&utm_campaign=3Dup-comment-free=
&utm_content=3DheaderLogo#mainDashboard" style=3D" color: #3bd671 !=
important;"><img src=3D"https://cdn.mcauto-images-production.sendgrid.=
net/3e8054f26aace367/6a696f89-4c68-4736-83c3-c08df64e1a0d/549x79.png" =
alt=3D"UptimeRobot" width=3D"180" style=3D" max-width: 180px; display: =
inline-block;"></a>
</td>
<td style=3D"=
text-align: right; font-size: 12px;" align=3D"right">
<a href=3D"https://uptimerobot.com/dashboard?=
utm_source=3DalertMessage&utm_medium=3Demail&utm_campaign=3Dup-comment-free=
&utm_content=3DheaderLink#791612149" style=3D" color: #3bd671 !important; =
text-decoration: none;">Go to monitor &rarr;</a>
</td>
</tr>
</tbody>
</table>
<div>
<h1 style=3D"font-size: 36px; color: =
#ffffff; margin-top: 45px; margin-bottom: 10px; line-height: 28px;">
Buscarron is <span style=3D"color:#3bd671">up</span>.
</h1>
</div>
</div>
</div>
<div style=3D"max-width: 600px; margin: 30px auto 0 auto; padding: =
0 10px;">
<div style=3D"background: #ffffff; border-radius: 6px;=
box-shadow: 0 20px 40px 0 rgba(0,0,0,0.1); padding: 25px; border: 1px =
solid #efefef; font-size: 14px; margin-bottom: 25px;">
<div>
<p style=3D"line-height: 20px;">Hello etke.cc,</p>
<p style=3D"line-height: 20px;">The latest incident has =
been resolved and your monitor is up again. Good job!</p>
</div>
<div style=3D"padding: 20px; =
background-color: #f9f9f9; border-radius: 6px; margin-top: 25px; =
line-height: 16px;">
<div style=3D"font-size: 12px; color: =
#687790;">Monitor name</div>
<h2 style=3D"font-size: 14px; =
margin-bottom: 5px; margin-top: 3px;">Buscarron</h2>
<hr style=3D"border: 1px solid #dedede; border-bottom: 0; =
margin: 10px 0;">
<div style=3D"color: #687790; font-size: =
12px;">Checked URL</div>
<h2 style=3D"font-size: 14px; =
margin-bottom: 5px; margin-top: 3px; line-height: 16px;"><code>
<a href=3D"https://buscarron.etke.cc/_health" =
style=3D"color: #131a26 !important; text-decoration: none !=
important;">https://buscarron.etke.cc/_health</a></code></h2>
<hr style=3D"border: 1px solid #dedede; border-bottom: 0; =
margin: 10px 0;">
<div style=3D"color: #687790; font-size: =
12px;">Root cause</div>
<h2 style=3D"font-size: 14px; =
margin-bottom: 5px; margin-top: 3px;">
HTTP 502 - Bad =
Gateway
</h2>
<hr style=3D"border: 1px solid =
#dedede; border-bottom: 0; margin: 10px 0;">
<div =
style=3D"font-size: 12px; color: #687790;">Incident started at</div>
<h2 style=3D"font-size: 14px; margin-bottom: 5px; margin-top:=
3px;">2022-08-19 10:43:14</h2>
<hr style=3D"border: 1px =
solid #dedede; border-bottom: 0; margin: 10px 0;">
<div style=3D"font-size: 12px; color: #687790;">Resolved =
at</div>
<h2 style=3D"font-size: 14px; margin-bottom: 5px; =
margin-top: 3px;">2022-08-19 10:48:13</h2>
<hr =
style=3D"border: 1px solid #dedede; border-bottom: 0; margin: 10px 0;">
<div style=3D"font-size: 12px; color: =
#687790;">Duration</div>
<h2 style=3D"font-size: 14px; =
margin-bottom: 5px; margin-top: 3px;">4 minutes and 59 seconds</h2>
<div style=3D"text-align: center; padding: 15px 0;">
<table>
<tr>
<td>
<table border=3D"0" cellspacing=3D"0" =
cellpadding=3D"0">
<tr>
=
<td align=3D"left" style=3D"border-radius: 25px; background-color: =
#3bd671; text-align: center;">
<a =
href=3D"https://uptimerobot.com/dashboard?incidentId=3D130160577&utm_source=
=3DalertMessage&utm_medium=3Demail&utm_campaign=3Dup-comment-free&utm_conte=
nt=3DviewIncident#mainDashboard" target=3D"_blank" style=3D"font-size: =
16px; color: #ffffff !important; font-weight: bold; text-decoration: =
none;border-radius: 25px; padding: 12px 25px; border: 1px solid #3bd671; =
display: inline-block;">View incident details</a>
=
</td>
</tr>
</table>
</td>
<td align=3D"left" =
style=3D"border-radius: 25px; text-align: center; padding-left: 10px;">
<a href=3D"https://uptimerobot.com/dashboard?=
incidentId=3D130160577&utm_source=3DalertMessage&utm_medium=3Demail&utm_cam=
paign=3Dup-comment-free&utm_content=3DcommentIncident#mainDashboard" =
target=3D"_blank" style=3D"font-size: 16px; color: #3bd671 !important; =
font-weight: bold; text-decoration: none; border-radius: 25px; padding: =
12px 25px; border: 1px solid #3bd671; display: inline-block;">Comment =
incident</a>
</td>
</tr>
</table>
</div>
</div>
</div>
<div style=3D'margin-bottom: 25px;'>
<table style=3D'width: 100%;'>
<tr>
<td
style=3D'background: #131a26; color: #ffffff; border-radius: 6px; =
box-shadow: 0 20px 40px 0 rgba(0,0,0,0.1); padding: 25px; border: 1px solid=
#efefef; font-size: 14px; border: 0;'>
<h2>
<strong style=3D"color: =
orange;">TIP:</strong> Resolve incidents, write a post mortem, rinse and =
repeat!
</h2>
<p>
Comment the incidents, so you can analyze what happened=
, when and why, to overcome the issues in the future. <strong><a =
href=3D"https://uptimerobot.com/dashboard?incidentId=3D130160577&utm_source=
=3DalertMessage&utm_medium=3Demail&utm_campaign=3DupCommentFree&utm_content=
=3DupsellCTA" style=3D"color: #3bd671;">Find out more</a>
</p>
</td>
</tr>
</table>
</div>
<div style=3D"border-top: 1px solid #dedede; font-size: 12px; =
color: #687790; text-align: center; padding: 25px 0;">
This email was sent by
<a =
href=3D"https://uptimerobot.com/?utm_source=3DalertMessage&utm_medium=3Dema=
il&utm_campaign=3Dup-comment-free&utm_content=3DfooterLink" style=3D"color:=
#3bd671 !important;">UptimeRobot</a>.
You can update your =
alert preferences in the <a href=3D"https://uptimerobot.com/dashboard?=
utm_source=3DalertMessage&utm_medium=3Demail&utm_campaign=3Dup-comment-free=
&utm_content=3DfooterSetting" style=3D" color: #3bd671 !=
important;">dashboard</a>.
</div>
</div>
</div>
</body>
</html>

10
go.mod
View File

@@ -5,6 +5,7 @@ go 1.18
require ( require (
github.com/emersion/go-smtp v0.15.0 github.com/emersion/go-smtp v0.15.0
github.com/getsentry/sentry-go v0.13.0 github.com/getsentry/sentry-go v0.13.0
github.com/jhillyerd/enmime v0.10.0
github.com/lib/pq v1.10.6 github.com/lib/pq v1.10.6
github.com/mattn/go-sqlite3 v1.14.14 github.com/mattn/go-sqlite3 v1.14.14
gitlab.com/etke.cc/go/env v1.0.0 gitlab.com/etke.cc/go/env v1.0.0
@@ -14,13 +15,21 @@ require (
) )
require ( require (
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 // indirect
github.com/google/go-cmp v0.5.8 // indirect github.com/google/go-cmp v0.5.8 // indirect
github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.12 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rs/zerolog v1.27.0 // indirect github.com/rs/zerolog v1.27.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/tidwall/gjson v1.14.3 // indirect github.com/tidwall/gjson v1.14.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
@@ -29,6 +38,7 @@ require (
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
maunium.net/go/maulogger/v2 v2.3.2 // indirect maunium.net/go/maulogger/v2 v2.3.2 // indirect
) )

33
go.sum
View File

@@ -1,5 +1,8 @@
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
@@ -8,13 +11,21 @@ github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVR
github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo= github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo=
github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0= github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 h1:gBeyun7mySAKWg7Fb0GOcv0upX9bdaZScs8QcRo8mEY=
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:g0fAGBisHaEQ0TRq1iBvemFRf+8AEWEmBESSiWB3Vsc=
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
github.com/jhillyerd/enmime v0.10.0 h1:DZEzhptPRBesvN3gf7K1BOh4rfpqdsdrEoxW1Edr/3s=
github.com/jhillyerd/enmime v0.10.0/go.mod h1:Qpe8EEemJMFAF8+NZoWdpXvK2Yb9dRF0k/z6mkcDHsA=
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
@@ -23,15 +34,28 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
@@ -52,15 +76,24 @@ gitlab.com/etke.cc/linkpearl v0.0.0-20220816155856-8f4cd5cce574 h1:9uWcP8vME9gPJ
gitlab.com/etke.cc/linkpearl v0.0.0-20220816155856-8f4cd5cce574/go.mod h1:CqwzwxVogKG6gDWTPTen3NyWbTESg42jxoTfXXwDGKQ= gitlab.com/etke.cc/linkpearl v0.0.0-20220816155856-8f4cd5cce574/go.mod h1:CqwzwxVogKG6gDWTPTen3NyWbTESg42jxoTfXXwDGKQ=
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c= golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c=
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210501142056-aec3718b3fa0/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/maulogger/v2 v2.3.2 h1:1XmIYmMd3PoQfp9J+PaHhpt80zpfmMqaShzUTC7FwY0= maunium.net/go/maulogger/v2 v2.3.2 h1:1XmIYmMd3PoQfp9J+PaHhpt80zpfmMqaShzUTC7FwY0=

View File

@@ -2,6 +2,7 @@ package smtp
import ( import (
"context" "context"
"os"
"time" "time"
"github.com/emersion/go-smtp" "github.com/emersion/go-smtp"
@@ -46,6 +47,9 @@ func Start(domain, port, loglevel string, client Client) error {
s.ReadTimeout = 10 * time.Second s.ReadTimeout = 10 * time.Second
s.WriteTimeout = 10 * time.Second s.WriteTimeout = 10 * time.Second
s.MaxMessageBytes = 63 * 1024 s.MaxMessageBytes = 63 * 1024
if log.GetLevel() == "DEBUG" || log.GetLevel() == "TRACE" {
s.Debug = os.Stdout
}
log.Info("Starting SMTP server on %s:%s", domain, port) log.Info("Starting SMTP server on %s:%s", domain, port)
return s.ListenAndServe() return s.ListenAndServe()

View File

@@ -6,7 +6,9 @@ import (
"github.com/emersion/go-smtp" "github.com/emersion/go-smtp"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
"github.com/jhillyerd/enmime"
"gitlab.com/etke.cc/go/logger" "gitlab.com/etke.cc/go/logger"
"gitlab.com/etke.cc/postmoogle/utils"
) )
type session struct { type session struct {
@@ -33,13 +35,14 @@ func (s *session) Rcpt(to string) error {
s.log.Error("cannot get mappings: %v", err) s.log.Error("cannot get mappings: %v", err)
return err return err
} }
_, ok := mappings[to] s.log.Debug("mappings: %v", mappings)
_, ok := mappings[utils.Mailbox(to)]
if !ok { if !ok {
s.log.Debug("mapping for %s not found", to) s.log.Debug("mapping for %s not found", to)
return smtp.ErrAuthRequired return smtp.ErrAuthRequired
} }
if Domain(to) != s.domain { if utils.Hostname(to) != s.domain {
s.log.Debug("wrong domain of %s", to) s.log.Debug("wrong domain of %s", to)
return smtp.ErrAuthRequired return smtp.ErrAuthRequired
} }
@@ -50,12 +53,16 @@ func (s *session) Rcpt(to string) error {
} }
func (s *session) Data(r io.Reader) error { func (s *session) Data(r io.Reader) error {
b, err := io.ReadAll(r) parser := enmime.NewParser()
env, err := parser.ReadEnvelope(r)
if err != nil { if err != nil {
s.log.Error("cannot read data: %v", err)
return err return err
} }
return s.client.Send(s.from, s.to, "", string(b)) text := env.Text
if env.HTML != "" {
text = env.HTML
}
return s.client.Send(s.from, s.to, env.GetHeader("Subject"), text)
} }
func (s *session) Reset() {} func (s *session) Reset() {}

View File

@@ -9,5 +9,5 @@ import (
// Client interface to send emails // Client interface to send emails
type Client interface { type Client interface {
GetMappings(context.Context) (map[string]id.RoomID, error) GetMappings(context.Context) (map[string]id.RoomID, error)
Send(from, to, subject, body string) error Send(from, mailbox, subject, body string) error
} }

View File

@@ -1,7 +0,0 @@
package smtp
import "strings"
func Domain(email string) string {
return email[strings.LastIndex(email, "@")+1:]
}

15
utils/utils.go Normal file
View File

@@ -0,0 +1,15 @@
package utils
import "strings"
func Mailbox(email string) string {
index := strings.LastIndex(email, "@")
if index == -1 {
return email
}
return email[:strings.LastIndex(email, "@")]
}
func Hostname(email string) string {
return email[strings.LastIndex(email, "@")+1:]
}