-
Notifications
You must be signed in to change notification settings - Fork 581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fixing redial issue, in case of error we need to dial again #123
base: master
Are you sure you want to change the base?
fixing redial issue, in case of error we need to dial again #123
Conversation
@alexcesaro please review and merge |
@alexcesaro not sure why its failing build https://travis-ci.org/go-gomail/gomail/builds/414841472?utm_source=github_status&utm_medium=notification .please help |
see #108 |
@@ -144,14 +144,12 @@ type smtpSender struct { | |||
|
|||
func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { | |||
if err := c.Mail(from); err != nil { | |||
if err == io.EOF { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an important distinction in error handling here: Gomail shouldn't make any attempts to redial unless it was explicitly an EOF. Any failure should instead be handled by the caller.
@arundudeemmt You mentioned in #104 that QOR relies on Gomail. Could you link me to where in the codebase it's used? I'd recommend extending that project to account for errors as it isn't always the best choice to simply redial without any additional work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some time there are error which are not EOF too and requires a redial like write: broken pipe .For broken pipe i was not able to find any standard error codes from smtp .Please suggest a way to fix the same .
IMO broken pipe comes when there is no event in last x time frame and pipe is broken .So three ways to fix i see it as 1) redial 2)build a keep alive mechanism and keep pinging server after x interval where x is less than time out interval 3)close connection after every email and then redial
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ivy @pedromorgan did you got a chance to look at this ?
@arundudeemmt This might actually be fixed in go-mail/mail@45ab546. Could you give go-mail a try and let us know if you still see this bug? |
@ivy i tried go-mail .it also has same issue as with go-gomail .After certain time interval , get write pipe broken error . |
@pedromorgan @ivy please help us in closing this quickly.. we are about to roll out QOR in production and using this go-mail module ... this has kind of bottleneck ... trying to close it from quite a while ..... i am hoping if this fix gets in library then use updated library else will have to our forked version with custom fix in it which i dont wish to do |
@cryptix: I was looking through QOR and noticed you submitted qor/mailer#1 to solve a similar issue. Is that at all related to this issue? From looking at the repo, it also looks like they might not have switched to go-mail like they intended in qor/mailer@0555e49#diff-04c6e90faac2675aa89e2176d2eec7d8R17 @arundudeemmt I don't want to stop you from going to production so definitely don't hesitate to use your own fork in the meantime. I do have a responsibility though to ensure every bug fix has a minimal impact on the other users of this library. I just have a couple questions still:
Thank you for being patient. We should be able to finally resolve this once we have all the details. 😄 |
@ivy: yup, spot on. It is also the reason I opened go-mail#15. |
@ivy - This is in continuation to the problem faced by @arundudeemmt . Please help in resolving the issue. Thanks! |
@jagritisinghal That error's coming directly from the SMTP server you're connected to. I imagine your connection's sitting idle for some time until Gmail decides to close it, right? Unfortunately, this library can only attempt to redial when the client-side times out. Otherwise, we end up dealing with lots of edge cases. SMTP services are wildly different and all have their own errors. See go-mail#15 (comment) for the discussion we're having around that. I'd recommend making your fix in qor/mailer (or wherever you're interacting with go-mail) in the meantime and construct a new |
@ivy if you dont mind , can you please explain is there any downside of redial if there is any kind of error ? Thats ways we can tackle many error cases and make this mail module more reliable IMO . |
@arundudeemmt one of the Go Proverbs (a Go idiom) is this:
But what does this mean? It means when looking to see if an error occurred, it should not be a binary evaluation. Instead you should inspect the error, and understand how you can handle that specific error case. In this patch, we aren't handling the error gracefully. We are only checking it, and taking an action no matter the result. I don't feel this is a safe default, nor is it idiomatic Go. |
@arundudeemmt The biggest downside of simply redialing is that you could find yourself being blacklisted by email services. For example, if one day your credentials changed, your application would constantly reconnect and be immediately disconnected. After too many failures, most services will simply ban your IP address for a few hours and depending on how long it takes you to resolve things on your end, that ban could extend to a few days. If I were to lay things out, I'd say: 1. Log your errorsThe most important thing you should be doing when recovering from a delivery error is to log it somewhere where you'll be able to see it. An error notifier like Sentry, some log aggregation service, or even something as simple as a Slack channel would work fine, just be sure that you're keeping track of it so you're never surprised. That alone will save you from the worst case scenario. 2. Implement a reconnect backoffThe next best thing is to add a reconnect backoff. Good clients wait a short time before redialing. It prevents my earlier example from getting worse because you'll be increasing that retry delay each time a connect fails. 3. Dial & close or use a connection poolLastly, go-mail's SMTP sender is intended to be closed when you no longer need it. If you're planning to have one-off deliveries as part of an HTTP transaction, you should probably close the connection when you're done with it. Otherwise, if you're processing large batches in the background somewhere, it's a good idea to have a wrapper responsible for maintaining the connection (possibly multiple connections) and redialing in the event of an error. Connection pooling is a bit too much to explain here but that's one feature that go-mail could seriously benefit from. I hope that answers your questions. If you need any more assistance, let me know. 😄 |
this is fix for issue #121