1
0

smtp_server_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. package server
  2. import (
  3. "github.com/emersion/go-smtp"
  4. "github.com/stretchr/testify/require"
  5. "io"
  6. "net"
  7. "net/http"
  8. "strings"
  9. "testing"
  10. )
  11. func TestSmtpBackend_Multipart(t *testing.T) {
  12. email := `MIME-Version: 1.0
  13. Date: Tue, 28 Dec 2021 00:30:10 +0100
  14. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  15. Subject: and one more
  16. From: Phil <phil@example.com>
  17. To: ntfy-mytopic@ntfy.sh
  18. Content-Type: multipart/alternative; boundary="000000000000f3320b05d42915c9"
  19. --000000000000f3320b05d42915c9
  20. Content-Type: text/plain; charset="UTF-8"
  21. what's up
  22. --000000000000f3320b05d42915c9
  23. Content-Type: text/html; charset="UTF-8"
  24. <div dir="ltr">what&#39;s up<br clear="all"><div><br></div></div>
  25. --000000000000f3320b05d42915c9--`
  26. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  27. require.Equal(t, "/mytopic", r.URL.Path)
  28. require.Equal(t, "and one more", r.Header.Get("Title"))
  29. require.Equal(t, "what's up", readAll(t, r.Body))
  30. })
  31. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  32. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  33. require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh"))
  34. require.Nil(t, session.Data(strings.NewReader(email)))
  35. }
  36. func TestSmtpBackend_MultipartNoBody(t *testing.T) {
  37. email := `MIME-Version: 1.0
  38. Date: Tue, 28 Dec 2021 01:33:34 +0100
  39. Message-ID: <CAAvm7ABCDsi9vsuu0WTRXzZQBC8dXrDOLT8iCWdqrsmg@mail.gmail.com>
  40. Subject: This email has a subject but no body
  41. From: Phil <phil@example.com>
  42. To: ntfy-emailtest@ntfy.sh
  43. Content-Type: multipart/alternative; boundary="000000000000bcf4a405d429f8d4"
  44. --000000000000bcf4a405d429f8d4
  45. Content-Type: text/plain; charset="UTF-8"
  46. --000000000000bcf4a405d429f8d4
  47. Content-Type: text/html; charset="UTF-8"
  48. <div dir="ltr"><br></div>
  49. --000000000000bcf4a405d429f8d4--`
  50. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  51. require.Equal(t, "/emailtest", r.URL.Path)
  52. require.Equal(t, "", r.Header.Get("Title")) // We flipped message and body
  53. require.Equal(t, "This email has a subject but no body", readAll(t, r.Body))
  54. })
  55. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  56. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  57. require.Nil(t, session.Rcpt("ntfy-emailtest@ntfy.sh"))
  58. require.Nil(t, session.Data(strings.NewReader(email)))
  59. }
  60. func TestSmtpBackend_Plaintext(t *testing.T) {
  61. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  62. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  63. Subject: and one more
  64. From: Phil <phil@example.com>
  65. To: mytopic@ntfy.sh
  66. Content-Type: text/plain; charset="UTF-8"
  67. what's up
  68. `
  69. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  70. require.Equal(t, "/mytopic", r.URL.Path)
  71. require.Equal(t, "and one more", r.Header.Get("Title"))
  72. require.Equal(t, "what's up", readAll(t, r.Body))
  73. })
  74. conf.SMTPServerAddrPrefix = ""
  75. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  76. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  77. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  78. require.Nil(t, session.Data(strings.NewReader(email)))
  79. }
  80. func TestSmtpBackend_Plaintext_No_ContentType(t *testing.T) {
  81. email := `Subject: Very short mail
  82. what's up
  83. `
  84. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  85. require.Equal(t, "/mytopic", r.URL.Path)
  86. require.Equal(t, "Very short mail", r.Header.Get("Title"))
  87. require.Equal(t, "what's up", readAll(t, r.Body))
  88. })
  89. conf.SMTPServerAddrPrefix = ""
  90. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  91. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  92. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  93. require.Nil(t, session.Data(strings.NewReader(email)))
  94. }
  95. func TestSmtpBackend_Plaintext_EncodedSubject(t *testing.T) {
  96. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  97. Subject: =?UTF-8?B?VGhyZWUgc2FudGFzIPCfjoXwn46F8J+OhQ==?=
  98. From: Phil <phil@example.com>
  99. To: ntfy-mytopic@ntfy.sh
  100. Content-Type: text/plain; charset="UTF-8"
  101. what's up
  102. `
  103. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  104. require.Equal(t, "Three santas 🎅🎅🎅", r.Header.Get("Title"))
  105. })
  106. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  107. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  108. require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh"))
  109. require.Nil(t, session.Data(strings.NewReader(email)))
  110. }
  111. func TestSmtpBackend_Plaintext_TooLongTruncate(t *testing.T) {
  112. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  113. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  114. Subject: and one more
  115. From: Phil <phil@example.com>
  116. To: mytopic@ntfy.sh
  117. Content-Type: text/plain; charset="UTF-8"
  118. you know this is a string.
  119. it's a long string.
  120. it's supposed to be longer than the max message length
  121. which is 4096 bytes,
  122. it used to be 512 bytes, but I increased that for the UnifiedPush support
  123. the 512 bytes was a little short, some people said
  124. but it kinda makes sense when you look at what it looks like one a phone
  125. heck this wasn't even half of it so far.
  126. so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA
  127. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  128. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
  129. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  130. ......................................................................
  131. ......................................................................
  132. ......................................................................
  133. ......................................................................
  134. ......................................................................
  135. ......................................................................
  136. ......................................................................
  137. ......................................................................
  138. ......................................................................
  139. ......................................................................
  140. ......................................................................
  141. ......................................................................
  142. ......................................................................
  143. ......................................................................
  144. ......................................................................
  145. ......................................................................
  146. ......................................................................
  147. ......................................................................
  148. ......................................................................
  149. ......................................................................
  150. ......................................................................
  151. ......................................................................
  152. ......................................................................
  153. ......................................................................
  154. ......................................................................
  155. ......................................................................
  156. ......................................................................
  157. ......................................................................
  158. ......................................................................
  159. ......................................................................
  160. ......................................................................
  161. ......................................................................
  162. ......................................................................
  163. ......................................................................
  164. ......................................................................
  165. ......................................................................
  166. ......................................................................
  167. ......................................................................
  168. ......................................................................
  169. ......................................................................
  170. ......................................................................
  171. ......................................................................
  172. ......................................................................
  173. ......................................................................
  174. ......................................................................
  175. ......................................................................
  176. ......................................................................
  177. ......................................................................
  178. and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  179. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  180. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  181. that should do it
  182. `
  183. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  184. expected := `you know this is a string.
  185. it's a long string.
  186. it's supposed to be longer than the max message length
  187. which is 4096 bytes,
  188. it used to be 512 bytes, but I increased that for the UnifiedPush support
  189. the 512 bytes was a little short, some people said
  190. but it kinda makes sense when you look at what it looks like one a phone
  191. heck this wasn't even half of it so far.
  192. so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA
  193. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  194. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
  195. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  196. ......................................................................
  197. ......................................................................
  198. ......................................................................
  199. ......................................................................
  200. ......................................................................
  201. ......................................................................
  202. ......................................................................
  203. ......................................................................
  204. ......................................................................
  205. ......................................................................
  206. ......................................................................
  207. ......................................................................
  208. ......................................................................
  209. ......................................................................
  210. ......................................................................
  211. ......................................................................
  212. ......................................................................
  213. ......................................................................
  214. ......................................................................
  215. ......................................................................
  216. ......................................................................
  217. ......................................................................
  218. ......................................................................
  219. ......................................................................
  220. ......................................................................
  221. ......................................................................
  222. ......................................................................
  223. ......................................................................
  224. ......................................................................
  225. ......................................................................
  226. ......................................................................
  227. ......................................................................
  228. ......................................................................
  229. ......................................................................
  230. ......................................................................
  231. ......................................................................
  232. ......................................................................
  233. ......................................................................
  234. ......................................................................
  235. ......................................................................
  236. ......................................................................
  237. ......................................................................
  238. ......................................................................
  239. ......................................................................
  240. ......................................................................
  241. ......................................................................
  242. ......................................................................
  243. ......................................................................
  244. and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  245. BBBBBBBBBBBBBBBBBBBBBBBBB`
  246. require.Equal(t, 4096, len(expected)) // Sanity check
  247. require.Equal(t, expected, readAll(t, r.Body))
  248. })
  249. conf.SMTPServerAddrPrefix = ""
  250. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  251. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  252. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  253. require.Nil(t, session.Data(strings.NewReader(email)))
  254. }
  255. func TestSmtpBackend_Unsupported(t *testing.T) {
  256. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  257. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  258. Subject: and one more
  259. From: Phil <phil@example.com>
  260. To: mytopic@ntfy.sh
  261. Content-Type: text/SOMETHINGELSE
  262. what's up
  263. `
  264. conf, backend := newTestBackend(t, func(http.ResponseWriter, *http.Request) {
  265. // Nothing.
  266. })
  267. conf.SMTPServerAddrPrefix = ""
  268. session, _ := backend.Login(fakeConnState(t, "1.2.3.4"), "user", "pass")
  269. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  270. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  271. require.Equal(t, errUnsupportedContentType, session.Data(strings.NewReader(email)))
  272. }
  273. func newTestBackend(t *testing.T, handler func(http.ResponseWriter, *http.Request)) (*Config, *smtpBackend) {
  274. conf := newTestConfig(t)
  275. conf.SMTPServerListen = ":25"
  276. conf.SMTPServerDomain = "ntfy.sh"
  277. conf.SMTPServerAddrPrefix = "ntfy-"
  278. backend := newMailBackend(conf, handler)
  279. return conf, backend
  280. }
  281. func readAll(t *testing.T, rc io.ReadCloser) string {
  282. b, err := io.ReadAll(rc)
  283. if err != nil {
  284. t.Fatal(err)
  285. }
  286. return string(b)
  287. }
  288. func fakeConnState(t *testing.T, remoteAddr string) *smtp.ConnectionState {
  289. ip, err := net.ResolveIPAddr("ip", remoteAddr)
  290. if err != nil {
  291. t.Fatal(err)
  292. }
  293. return &smtp.ConnectionState{
  294. Hostname: "myhostname",
  295. LocalAddr: ip,
  296. RemoteAddr: ip,
  297. }
  298. }