smtp_server_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. package server
  2. import (
  3. "github.com/emersion/go-smtp"
  4. "github.com/stretchr/testify/require"
  5. "net"
  6. "net/http"
  7. "strings"
  8. "testing"
  9. )
  10. func TestSmtpBackend_Multipart(t *testing.T) {
  11. email := `MIME-Version: 1.0
  12. Date: Tue, 28 Dec 2021 00:30:10 +0100
  13. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  14. Subject: and one more
  15. From: Phil <phil@example.com>
  16. To: ntfy-mytopic@ntfy.sh
  17. Content-Type: multipart/alternative; boundary="000000000000f3320b05d42915c9"
  18. --000000000000f3320b05d42915c9
  19. Content-Type: text/plain; charset="UTF-8"
  20. what's up
  21. --000000000000f3320b05d42915c9
  22. Content-Type: text/html; charset="UTF-8"
  23. <div dir="ltr">what&#39;s up<br clear="all"><div><br></div></div>
  24. --000000000000f3320b05d42915c9--`
  25. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  26. require.Equal(t, "/mytopic", r.URL.Path)
  27. require.Equal(t, "and one more", r.Header.Get("Title"))
  28. require.Equal(t, "what's up", readAll(t, r.Body))
  29. })
  30. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  31. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  32. require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh"))
  33. require.Nil(t, session.Data(strings.NewReader(email)))
  34. }
  35. func TestSmtpBackend_MultipartNoBody(t *testing.T) {
  36. email := `MIME-Version: 1.0
  37. Date: Tue, 28 Dec 2021 01:33:34 +0100
  38. Message-ID: <CAAvm7ABCDsi9vsuu0WTRXzZQBC8dXrDOLT8iCWdqrsmg@mail.gmail.com>
  39. Subject: This email has a subject but no body
  40. From: Phil <phil@example.com>
  41. To: ntfy-emailtest@ntfy.sh
  42. Content-Type: multipart/alternative; boundary="000000000000bcf4a405d429f8d4"
  43. --000000000000bcf4a405d429f8d4
  44. Content-Type: text/plain; charset="UTF-8"
  45. --000000000000bcf4a405d429f8d4
  46. Content-Type: text/html; charset="UTF-8"
  47. <div dir="ltr"><br></div>
  48. --000000000000bcf4a405d429f8d4--`
  49. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  50. require.Equal(t, "/emailtest", r.URL.Path)
  51. require.Equal(t, "", r.Header.Get("Title")) // We flipped message and body
  52. require.Equal(t, "This email has a subject but no body", readAll(t, r.Body))
  53. })
  54. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  55. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  56. require.Nil(t, session.Rcpt("ntfy-emailtest@ntfy.sh"))
  57. require.Nil(t, session.Data(strings.NewReader(email)))
  58. }
  59. func TestSmtpBackend_Plaintext(t *testing.T) {
  60. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  61. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  62. Subject: and one more
  63. From: Phil <phil@example.com>
  64. To: mytopic@ntfy.sh
  65. Content-Type: text/plain; charset="UTF-8"
  66. what's up
  67. `
  68. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  69. require.Equal(t, "/mytopic", r.URL.Path)
  70. require.Equal(t, "and one more", r.Header.Get("Title"))
  71. require.Equal(t, "what's up", readAll(t, r.Body))
  72. })
  73. conf.SMTPServerAddrPrefix = ""
  74. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  75. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  76. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  77. require.Nil(t, session.Data(strings.NewReader(email)))
  78. }
  79. func TestSmtpBackend_Plaintext_No_ContentType(t *testing.T) {
  80. email := `Subject: Very short mail
  81. what's up
  82. `
  83. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  84. require.Equal(t, "/mytopic", r.URL.Path)
  85. require.Equal(t, "Very short mail", r.Header.Get("Title"))
  86. require.Equal(t, "what's up", readAll(t, r.Body))
  87. })
  88. conf.SMTPServerAddrPrefix = ""
  89. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  90. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  91. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  92. require.Nil(t, session.Data(strings.NewReader(email)))
  93. }
  94. func TestSmtpBackend_Plaintext_EncodedSubject(t *testing.T) {
  95. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  96. Subject: =?UTF-8?B?VGhyZWUgc2FudGFzIPCfjoXwn46F8J+OhQ==?=
  97. From: Phil <phil@example.com>
  98. To: ntfy-mytopic@ntfy.sh
  99. Content-Type: text/plain; charset="UTF-8"
  100. what's up
  101. `
  102. _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  103. require.Equal(t, "Three santas ๐ŸŽ…๐ŸŽ…๐ŸŽ…", r.Header.Get("Title"))
  104. })
  105. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  106. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  107. require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh"))
  108. require.Nil(t, session.Data(strings.NewReader(email)))
  109. }
  110. func TestSmtpBackend_Plaintext_TooLongTruncate(t *testing.T) {
  111. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  112. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  113. Subject: and one more
  114. From: Phil <phil@example.com>
  115. To: mytopic@ntfy.sh
  116. Content-Type: text/plain; charset="UTF-8"
  117. you know this is a string.
  118. it's a long string.
  119. it's supposed to be longer than the max message length
  120. which is 4096 bytes,
  121. it used to be 512 bytes, but I increased that for the UnifiedPush support
  122. the 512 bytes was a little short, some people said
  123. but it kinda makes sense when you look at what it looks like one a phone
  124. heck this wasn't even half of it so far.
  125. so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA
  126. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  127. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
  128. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  129. ......................................................................
  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. and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  178. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  179. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  180. that should do it
  181. `
  182. conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) {
  183. expected := `you know this is a string.
  184. it's a long string.
  185. it's supposed to be longer than the max message length
  186. which is 4096 bytes,
  187. it used to be 512 bytes, but I increased that for the UnifiedPush support
  188. the 512 bytes was a little short, some people said
  189. but it kinda makes sense when you look at what it looks like one a phone
  190. heck this wasn't even half of it so far.
  191. so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA
  192. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  193. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
  194. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  195. ......................................................................
  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. and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  244. BBBBBBBBBBBBBBBBBBBBBBBBB`
  245. require.Equal(t, 4096, len(expected)) // Sanity check
  246. require.Equal(t, expected, readAll(t, r.Body))
  247. })
  248. conf.SMTPServerAddrPrefix = ""
  249. session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4"))
  250. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  251. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  252. require.Nil(t, session.Data(strings.NewReader(email)))
  253. }
  254. func TestSmtpBackend_Unsupported(t *testing.T) {
  255. email := `Date: Tue, 28 Dec 2021 00:30:10 +0100
  256. Message-ID: <CAAvm79YP0C=Rt1N=KWmSUBB87KK2rRChmdzKqF1vCwMEUiVzLQ@mail.gmail.com>
  257. Subject: and one more
  258. From: Phil <phil@example.com>
  259. To: mytopic@ntfy.sh
  260. Content-Type: text/SOMETHINGELSE
  261. what's up
  262. `
  263. conf, backend := newTestBackend(t, func(http.ResponseWriter, *http.Request) {
  264. // Nothing.
  265. })
  266. conf.SMTPServerAddrPrefix = ""
  267. session, _ := backend.Login(fakeConnState(t, "1.2.3.4"), "user", "pass")
  268. require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{}))
  269. require.Nil(t, session.Rcpt("mytopic@ntfy.sh"))
  270. require.Equal(t, errUnsupportedContentType, session.Data(strings.NewReader(email)))
  271. }
  272. func newTestBackend(t *testing.T, handler func(http.ResponseWriter, *http.Request)) (*Config, *smtpBackend) {
  273. conf := newTestConfig(t)
  274. conf.SMTPServerListen = ":25"
  275. conf.SMTPServerDomain = "ntfy.sh"
  276. conf.SMTPServerAddrPrefix = "ntfy-"
  277. backend := newMailBackend(conf, handler)
  278. return conf, backend
  279. }
  280. func fakeConnState(t *testing.T, remoteAddr string) *smtp.ConnectionState {
  281. ip, err := net.ResolveIPAddr("ip", remoteAddr)
  282. if err != nil {
  283. t.Fatal(err)
  284. }
  285. return &smtp.ConnectionState{
  286. Hostname: "myhostname",
  287. LocalAddr: ip,
  288. RemoteAddr: ip,
  289. }
  290. }