diff --git a/docs/releases.md b/docs/releases.md index 1ae4779..fc510e5 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -13,6 +13,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release * Fix `chown` issues with RHEL-like based systems ([#566](https://github.com/binwiederhier/ntfy/issues/566)/[#565](https://github.com/binwiederhier/ntfy/pull/565), thanks to [@danieldemus](https://github.com/danieldemus)) * Removed `upx` (binary packing) for all builds due to false virus warnings ([#576](https://github.com/binwiederhier/ntfy/issues/576), thanks to [@shawnhwei](https://github.com/shawnhwei) for reporting) +* Upgraded `go-smtp` library and tests to v0.16.0 ([#569](https://github.com/binwiederhier/ntfy/issues/569)) **Documentation:** diff --git a/go.mod b/go.mod index dda12d4..6cd4fd5 100644 --- a/go.mod +++ b/go.mod @@ -4,22 +4,22 @@ go 1.18 require ( cloud.google.com/go/firestore v1.9.0 // indirect - cloud.google.com/go/storage v1.28.1 // indirect + cloud.google.com/go/storage v1.29.0 // indirect github.com/BurntSushi/toml v1.2.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/emersion/go-smtp v0.15.0 + github.com/emersion/go-smtp v0.16.0 github.com/gabriel-vasile/mimetype v1.4.1 github.com/gorilla/websocket v1.5.0 github.com/mattn/go-sqlite3 v1.14.16 github.com/olebedev/when v0.0.0-20221205223600-4d190b02b8d8 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.23.7 - golang.org/x/crypto v0.4.0 - golang.org/x/oauth2 v0.3.0 // indirect + github.com/urfave/cli/v2 v2.24.3 + golang.org/x/crypto v0.6.0 + golang.org/x/oauth2 v0.5.0 // indirect golang.org/x/sync v0.1.0 - golang.org/x/term v0.3.0 + golang.org/x/term v0.5.0 golang.org/x/time v0.3.0 - google.golang.org/api v0.105.0 + google.golang.org/api v0.110.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -28,11 +28,11 @@ require github.com/pkg/errors v0.9.1 // indirect require firebase.google.com/go/v4 v4.10.0 require ( - cloud.google.com/go v0.107.0 // indirect - cloud.google.com/go/compute v1.14.0 // indirect + cloud.google.com/go v0.109.0 // indirect + cloud.google.com/go/compute v1.18.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.9.0 // indirect - cloud.google.com/go/longrunning v0.3.0 // indirect + cloud.google.com/go/iam v0.10.0 // indirect + cloud.google.com/go/longrunning v0.4.1 // indirect github.com/AlekSi/pointer v1.2.0 // indirect github.com/MicahParks/keyfunc v1.9.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -42,20 +42,20 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine/v2 v2.0.2 // indirect - google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect - google.golang.org/grpc v1.51.0 // indirect + google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect + google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0ad0057..2ee309f 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,28 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.109.0 h1:38CZoKGlCnPZjGdyj0ZfpoGae0/wgNfy5F0byyxg0Gk= +cloud.google.com/go v0.109.0/go.mod h1:2sYycXt75t/CSB5R9M2wPU1tJmire7AQZTPtITcGBVE= cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/iam v0.9.0 h1:bK6Or6mxhuL8lnj1i9j0yMo2wE/IeTO2cWlfUrf/TZs= cloud.google.com/go/iam v0.9.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= +cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= +cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= firebase.google.com/go/v4 v4.10.0 h1:dgK/8uwfJbzc5LZK/GyRRfIkZEDObN9q0kgEXsjlXN4= firebase.google.com/go/v4 v4.10.0/go.mod h1:m0gLwPY9fxKggizzglgCNWOGnFnVPifLpqZzo5u3e/A= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= @@ -35,6 +45,8 @@ github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8b github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-smtp v0.15.0 h1:3+hMGMGrqP/lqd7qoxZc1hTU8LY8gHV9RFGWlqSDmP8= github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= +github.com/emersion/go-smtp v0.16.0 h1:eB9CY9527WdEZSs5sWisTmilDX7gG+Q/2IdRcmubpa8= +github.com/emersion/go-smtp v0.16.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -77,6 +89,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -101,6 +115,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.24.3 h1:7Q1w8VN8yE0MJEHP06bv89PjYsN4IHWED2s1v/Zlfm0= +github.com/urfave/cli/v2 v2.24.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -109,6 +125,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -124,9 +142,13 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -140,15 +162,21 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -161,6 +189,8 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3j golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.105.0 h1:t6P9Jj+6XTn4U9I2wycQai6Q/Kz7iOT+QzjJ3G2V4x8= google.golang.org/api v0.105.0/go.mod h1:qh7eD5FJks5+BcE+cjBIm6Gz8vioK7EHvnlniqXBnqI= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -172,6 +202,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -179,6 +211,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/server/smtp_server_test.go b/server/smtp_server_test.go index be99d9e..80aa645 100644 --- a/server/smtp_server_test.go +++ b/server/smtp_server_test.go @@ -1,16 +1,23 @@ package server import ( + "bufio" "github.com/emersion/go-smtp" "github.com/stretchr/testify/require" + "io" "net" "net/http" "strings" "testing" + "time" ) func TestSmtpBackend_Multipart(t *testing.T) { - email := `MIME-Version: 1.0 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: ntfy-mytopic@ntfy.sh +DATA +MIME-Version: 1.0 Date: Tue, 28 Dec 2021 00:30:10 +0100 Message-ID: Subject: and one more @@ -28,20 +35,25 @@ Content-Type: text/html; charset="UTF-8"
what's up

---000000000000f3320b05d42915c9--` - _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { +--000000000000f3320b05d42915c9-- +. +` + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/mytopic", r.URL.Path) require.Equal(t, "and one more", r.Header.Get("Title")) require.Equal(t, "what's up", readAll(t, r.Body)) }) - session, _ := backend.NewSession(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", &smtp.MailOptions{})) - require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_MultipartNoBody(t *testing.T) { - email := `MIME-Version: 1.0 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: ntfy-emailtest@ntfy.sh +DATA +MIME-Version: 1.0 Date: Tue, 28 Dec 2021 01:33:34 +0100 Message-ID: Subject: This email has a subject but no body @@ -59,20 +71,25 @@ Content-Type: text/html; charset="UTF-8"

---000000000000bcf4a405d429f8d4--` - _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { +--000000000000bcf4a405d429f8d4-- +. +` + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/emailtest", r.URL.Path) require.Equal(t, "", r.Header.Get("Title")) // We flipped message and body require.Equal(t, "This email has a subject but no body", readAll(t, r.Body)) }) - session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("ntfy-emailtest@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_Plaintext(t *testing.T) { - email := `Date: Tue, 28 Dec 2021 00:30:10 +0100 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: mytopic@ntfy.sh +DATA +Date: Tue, 28 Dec 2021 00:30:10 +0100 Message-ID: Subject: and one more From: Phil @@ -80,56 +97,68 @@ To: mytopic@ntfy.sh Content-Type: text/plain; charset="UTF-8" what's up +. ` - conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { + s, c, conf, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/mytopic", r.URL.Path) require.Equal(t, "and one more", r.Header.Get("Title")) require.Equal(t, "what's up", readAll(t, r.Body)) }) conf.SMTPServerAddrPrefix = "" - session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("mytopic@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_Plaintext_No_ContentType(t *testing.T) { - email := `Subject: Very short mail + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: mytopic@ntfy.sh +DATA +Subject: Very short mail what's up +. ` - conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { + s, c, conf, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/mytopic", r.URL.Path) require.Equal(t, "Very short mail", r.Header.Get("Title")) require.Equal(t, "what's up", readAll(t, r.Body)) }) conf.SMTPServerAddrPrefix = "" - session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("mytopic@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_Plaintext_EncodedSubject(t *testing.T) { - email := `Date: Tue, 28 Dec 2021 00:30:10 +0100 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: ntfy-mytopic@ntfy.sh +DATA +Date: Tue, 28 Dec 2021 00:30:10 +0100 Subject: =?UTF-8?B?VGhyZWUgc2FudGFzIPCfjoXwn46F8J+OhQ==?= From: Phil To: ntfy-mytopic@ntfy.sh Content-Type: text/plain; charset="UTF-8" what's up +. ` - _, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "Three santas 🎅🎅🎅", r.Header.Get("Title")) }) - session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("ntfy-mytopic@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_Plaintext_TooLongTruncate(t *testing.T) { - email := `Date: Tue, 28 Dec 2021 00:30:10 +0100 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: mytopic@ntfy.sh +DATA +Date: Tue, 28 Dec 2021 00:30:10 +0100 Message-ID: Subject: and one more From: Phil @@ -148,60 +177,61 @@ so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB that should do it +. ` - conf, backend := newTestBackend(t, func(w http.ResponseWriter, r *http.Request) { + s, c, conf, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { expected := `you know this is a string. it's a long string. it's supposed to be longer than the max message length @@ -214,68 +244,71 @@ so i'm gonna fill the rest of this with AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... -...................................................................... +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp +pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp and with BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBB` require.Equal(t, 4096, len(expected)) // Sanity check require.Equal(t, expected, readAll(t, r.Body)) }) + defer s.Close() + defer c.Close() conf.SMTPServerAddrPrefix = "" - session, _ := backend.AnonymousLogin(fakeConnState(t, "1.2.3.4")) - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("mytopic@ntfy.sh")) - require.Nil(t, session.Data(strings.NewReader(email))) + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } func TestSmtpBackend_Unsupported(t *testing.T) { - email := `Date: Tue, 28 Dec 2021 00:30:10 +0100 + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: ntfy-mytopic@ntfy.sh +DATA +Date: Tue, 28 Dec 2021 00:30:10 +0100 Message-ID: Subject: and one more From: Phil @@ -283,34 +316,89 @@ To: mytopic@ntfy.sh Content-Type: text/SOMETHINGELSE what's up +. ` - conf, backend := newTestBackend(t, func(http.ResponseWriter, *http.Request) { - // Nothing. + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("This should not be called") }) - conf.SMTPServerAddrPrefix = "" - session, _ := backend.Login(fakeConnState(t, "1.2.3.4"), "user", "pass") - require.Nil(t, session.Mail("phil@example.com", smtp.MailOptions{})) - require.Nil(t, session.Rcpt("mytopic@ntfy.sh")) - require.Equal(t, errUnsupportedContentType, session.Data(strings.NewReader(email))) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "554 5.0.0 Error: transaction failed, blame it on the weather: unsupported content type") } -func newTestBackend(t *testing.T, handler func(http.ResponseWriter, *http.Request)) (*Config, *smtpBackend) { - conf := newTestConfig(t) +func TestSmtpBackend_InvalidAddress(t *testing.T) { + email := `EHLO example.com +MAIL FROM: phil@example.com +RCPT TO: unsupported@ntfy.sh +DATA +Date: Tue, 28 Dec 2021 00:30:10 +0100 +Subject: and one more +From: Phil +To: mytopic@ntfy.sh +Content-Type: text/plain + +what's up +. +` + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("This should not be called") + }) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "451 4.0.0 invalid address") +} + +type smtpHandlerFunc func(http.ResponseWriter, *http.Request) + +func newTestSMTPServer(t *testing.T, handler smtpHandlerFunc) (s *smtp.Server, c net.Conn, conf *Config, scanner *bufio.Scanner) { + conf = newTestConfig(t) conf.SMTPServerListen = ":25" conf.SMTPServerDomain = "ntfy.sh" conf.SMTPServerAddrPrefix = "ntfy-" backend := newMailBackend(conf, handler) - return conf, backend -} - -func fakeConnState(t *testing.T, remoteAddr string) *smtp.Conn { - ip, err := net.ResolveIPAddr("ip", remoteAddr) + l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } - return &smtp.Conn{ - Hostname: "myhostname", - LocalAddr: ip, - RemoteAddr: ip, + s = smtp.NewServer(backend) + s.Domain = conf.SMTPServerDomain + s.AllowInsecureAuth = true + go func() { + require.Nil(t, s.Serve(l)) + }() + c, err = net.Dial("tcp", l.Addr().String()) + if err != nil { + t.Fatal(err) } + scanner = bufio.NewScanner(c) + return +} + +func writeAndReadUntilLine(t *testing.T, email string, conn net.Conn, scanner *bufio.Scanner, expectedLine string) { + _, err := io.WriteString(conn, email) + require.Nil(t, err) + readUntilLine(t, conn, scanner, expectedLine) +} + +func readUntilLine(t *testing.T, conn net.Conn, scanner *bufio.Scanner, expectedLine string) { + cancelChan := make(chan bool) + go func() { + select { + case <-cancelChan: + case <-time.After(3 * time.Second): + conn.Close() + t.Error("Failed waiting for expected output") + } + }() + var output string + for scanner.Scan() { + text := scanner.Text() + if strings.TrimSpace(text) == expectedLine { + cancelChan <- true + return + } + output += text + "\n" + //fmt.Println(text) + } + t.Fatalf("Expected line '%s' not found in output:\n%s", expectedLine, output) }