go-mail / mail Goto Github PK
View Code? Open in Web Editor NEWThis project forked from go-gomail/gomail
Actively maintained fork of gomail. The best way to send emails in Go.
License: MIT License
This project forked from go-gomail/gomail
Actively maintained fork of gomail. The best way to send emails in Go.
License: MIT License
using this example: https://godoc.org/github.com/go-mail/mail#ex-package--Daemon.
the email gets sent however after 30 seconds it throws an error on s.Close()
error is: "write tcp [myipv6addr]:56186->[2a06:1700:0:b::c0cc]:465: i/o timeout". also tried different email providers, same issue
does anyone have any idea why?
Is anyone away of any implementations of SendFunc
that knows how to send the email message via a local sendmail
binary with fork/exec?
Per original issue go-gomail#126 this is still happening. The issue however does not occur when using the AttachReader() variant
Should we create a fork with an extended set of maintainers? Because this rather simple PR #72 is hanging there for a long time.
Also I would be willing to move this project to use go modules, if it doesn't already do it in newer versions.
Hi,
I just can't get my code to connect to gmail. My go code is:
m := mail.NewMessage()
m.SetHeader("From", from)
m.SetHeader("To", toList)
m.SetHeader("Subject", subject)
m.SetBody("text/html", msg)
m.AddAlternative("text/plain", msgText)
iport, _ := strconv.Atoi(port)
d := mail.NewDialer(host, iport, from, password)
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
b.err = err.Error();
return b.err
}
return "Success"
but it constantly comes back with username or password is incorrect. I've checked them and they are right and work with other clients. Not sure what else to try.
My client is sending emails...throttled 6 per minute...I use gomail to facilitate this...not that it's directly related. I wonder if anyone knows if using dialAndSend()
or anything regularly would cause Office 365 to prompt for his password in Outlook all the time. This is the only correlation I can think of is that he uses this Emailer almost daily now...sending over a 100 emails usually...sometimes more.
He changed the password and it seems to have stopped for now...but I'm curious if that might have had something to do with it...and if there's something that can be done to prevent it? Settings wise or anything.
These emails aren't spam or anything...he does his business via email...when they get new units in...he matches them to customers and the customized emails shoot out.
Before it was through a desktop app and the mailing was handed off to the installed Outlook instance...so this was never a problem.
Steve
I am suprised @ivy go-gomail#104
go-mail
org from our frustration/realisation, to try and move things forward, as maintainer missing go-gomail#104And then I added @ivy as an "owner" moving forward..
once i was away..
go-mail
and moving forwardSo now you have gone off onto your own planet... which is fine..
But good luck, keep up with the rest of us and this project is now exactly what the original problem was.
Good luck on your new independent maintainable fork,
Hi!
I'm using DialAndSend to send e-mail using a local postfix server. There's a way to get the postfix response (like 250 2.0.0 Ok: queued as C0E5C82029
)?
Thank you.
I use tom mail, go 1.10.2
host: smtp.tom.com
port: 25
d := mail.NewDialer(host, port, from, password)
d.SSL = false
I get "unencrypted connection", I can not send email use this library when use tom mail.
I found that using smtp-relay.gmail.com
while using the localhost
LocalName makes the library return an obscure EOF error, while the packet tracer reveals the actual response:
220 smtp-relay.gmail.com ESMTP f10sm1a4899ejl.97 - gsmtp
EHLO localhost
421 4.7.0 Try again later, closing connection. (EHLO) f10sm1a4899ejl.97 - gsmtp
HELO localhost
Specifying a different LocalName fixes the issue, still it makes it hard to debug, it'd be nice to check the server response in smtp.go:64
and return the server error instead of just EOF.
I’m confused by the multipart tree structure generated for a mail with alternate text and html, embed and attachment. Here is what go-mail generates:
multipart/mixed |-- multipart/related | |-- multipart/alternate | | |-- text/plain | | `-- text/html | `-- image/jpg `-- attachment
What I expected to see:
multipart/mixed |-- multipart/alternate | |-- text/plain | `-- multipart/related | |-- text/html | `-- image/jpg `-- attachment
This is the structure that I have seen in mails. Which one is correct ?
What is the point to associate (relate) the embedded image to the text/plain part ?
Originally reported in go-gomail#102, the error details are lost in Send()
due the use of fmt.Errorf. As mentioned in the original issue, we should allow smarter handling of errors by exposing the original error and index in a struct:
// A SendError represents the failed transmission of a Message and details the
// original error and index of the Message if it was part of a batch.
type SendError struct {
// Index specifies the index of the Message, if it was part of a batch.
Index uint
// Cause specifies the error detailing the original cause of the failure.
Cause error
}
func (err *SendError) Error() string {
return fmt.Sprintf("gomail: could not send email %d: %v",
err.Index, err.Cause)
}
For systems like Google's app engine (standard), out going sockets need a context (per incoming http connection). see: https://godoc.org/google.golang.org/appengine/socket
This makes it really hard when the netDialout command is global, since simultaneous requests are coming in. It's much more practical than before though.
Hi,
I'm using this fork and I can't figure out why the reconnect on timeout doesn't work.
I create a new Dialer
and Dial
right away. If the connection is established it works fine, but as soon as it gets a timeout it doesn't work anymore.
I get this error after getting the timeout:
gomail: could not send email 1: 421 3a031b949411: SMTP command timeout - closing connection
And following attempts to send emails return this error:
gomail: could not send email 1: write tcp 172.18.0.7:36196->172.18.0.3:25: write: broken pipe
If it matters, I use https://github.com/namshi/docker-smtp as a smtp server with no configuration at this point
Do I have to do anything special?
As it stands now, there are only unit tests that mock the behavior but don't actually interact with an SMTP server. I believe we can merge with more confidence if we can start testing against a locally running server.
func (w *messageWriter) writeString(s string) {
n, _ := io.WriteString(w.w, s)
w.n += int64(n)
}
Error return by io.WriteString is silently ignored.
Short summary: Non-ASCII filenames should be encoded following RFC 2047 in the name
parameter of the Content-Type
and RFC 2231 in the filename
parameter of the Content-Disposition
. For example, an attachment named 今日は世.txt
might include the following headers:
Content-Type: text/plain; charset=UTF-8; name=?UTF-8?Q?=E4=BB=8A=E6=97=A5=E3=81=AF=E4=B8=96.txt?=
Content-Disposition: attachment; filename*=%E4%BB%8A%E6%97%A5%E3%81%AF%E4%B8%96.txt
Any proposed fix should first be tested against a few major email clients.
Originally reported in go-gomail#66, non-ASCII filenames are garbled when attaching files to messages. In looking at some of the proposed solutions (go-gomail#83), some people have solved this by adding charset=UTF-8
to the Content-Type
header. This may work for some but that is almost certainly a coincidence which I expect causes more issues later for certain clients and attachments.
Digging into various IETF standards, none of the RFCs seem to specify filename encoding for non-ASCII characters. Take RFC 2183, section 2.3 for example:
Current [RFC 2045] grammar restricts parameter values (and hence
Content-Disposition filenames) to US-ASCII. We recognize the great
desirability of allowing arbitrary character sets in filenames, but
it is beyond the scope of this document to define the necessary
mechanisms.
This thread on the ietf-smtp mailing list seems to have the answer:
Finally, if you have to include filename information, either put it in a
filename= parameter or both a filename= and name= parameter. Never ever use
just a name= parameter because that opens you up to gratuitous interpretation
of the part using some disposition value you didn't intend. (I note in passing
that this is what Thunderbird now dows, with the added nuance of using
nonstandard RFC 2047 encoding for the name= paramter and standard RFC 2231
encoding for the filename= parameter.)
Hello,
I can't figure out how I can set a mutipart Content-Type according to rfc 3156 about PGP signed and encrypted MIME extension.
I need to produce something like this:
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
boundary="=-QywBjbY3n9IaXFyKL+oG"
Only related, mixed and alternative multipart sound supported according to openMultipart
method found here https://github.com/go-mail/mail/blob/v2/writeto.go
I use gomail in one of my projects and when I try to send emails concurrently I get a
fatal error : concurrent map writes
Below is my code to send an email
func (s *Service) sendEmail(notification *entities.Notification, m gomail.Message, errorNotificationIDs *[]int64, processedNotificationIDs *[]int64, wg *sync.WaitGroup) {
m.SetHeader("To", notification.Recipient)
if err := s.emailer.DialAndSend(&m); err != nil {
*errorNotificationIDs = append(*errorNotificationIDs, notification.ID)
} else {
*processedNotificationIDs = append(*processedNotificationIDs, notification.ID)
}
wg.Done()
}
//Usage of the above function
for i := 0; i < len(notifications); i += 10 {
batch := notifications[i:helper.Min(i+10, len(notifications))]
for _, notification := range batch {
wg.Add(1)
go s.sendEmail(notification, *m, &errorNotificationIDs, &processedNotificationIDs, &wg)
}
}
wg.Wait()
Panics like below
fatal error: concurrent map writes
goroutine 153 [running]:
runtime.throw(0x1c8d213, 0x15)
/usr/local/go/src/runtime/panic.go:616 +0x81 fp=0xc4203fb550 sp=0xc4203fb530 pc=0x1031551
runtime.mapassign_faststr(0x1b80be0, 0xc42041d0b0, 0x1c7fb31, 0x2, 0x1)
/usr/local/go/src/runtime/hashmap_fast.go:779 +0x4bd fp=0xc4203fb5d8 sp=0xc4203fb550 pc=0x100f9cd
gopkg.in/gomail%2ev2.(*Message).SetHeader(0xc4202e7340, 0x1c7fb31, 0x2, 0xc420254880, 0x1, 0x1)
/Users/abcd/go/src/gopkg.in/gomail.v2/message.go:103 +0x80 fp=0xc4203fb618 sp=0xc4203fb5d8 pc=0x1409570
email.(*Service).sendEmail(0xc4204b2d90, 0xc420343540, 0xc42041d0b0, 0xc42000e028, 0x1, 0x1, 0xc42000e040, 0x1, 0x1, 0xc42000e030, ...)
/Users/abcd/go/src/email/email.go:327 +0x134 fp=0xc4203fb6d8 sp=0xc4203fb618 pc=0x1a81b94
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4203fb6e0 sp=0xc4203fb6d8 pc=0x105eac1
created by email.(*Service).handleEmailMessage
/Users/abcd/go/src/email/email.go:166 +0x15e2
i get message wsarecv: An existing connection was forcibly closed by the remote host.
when i use DialAndSend
Is there a way to specify an email's priority (low, normal, or high)? If not, it would be helpful to include that feature, as it is a common method for email clients to prioritize incoming mail.
Thanks!
Thank you for the library :)
Line 60 in f59b9b8
This way of "detecting" SSL breaks freedom :)
A port number shouldn't be used as a law, instead, this should be configurable: even if assumption that 465 port is probably SSL, it should be just a sane default, not a strict law.
My Problem :
Emails are getting send even if it panics
i`m getting this error :
gomail: could not send email 1: open ./pdf/fd.pdf: no such file or directory
There is no pdf(thats right) . He gives me the error , panics, but the emails are still going out.
There is an empty file attached with the name of the file it couldn't find.
They are send inside a Goroutine.
d := mail.NewDialer(smtpserver, port, login, passwort)
seve, err := d.Dial()
if err != nil {
log.Fatal("Konnte keine Verbindung zum Mailserver herstellen")
}
---Goroutine starts---
//stuff for validating the email recipient
//stuff for getting email body
m := mail.NewMessage()
m.SetHeader("From", absender)
m.SetHeader("To", emails)
m.SetHeader("Subject", fmt.Sprintf(Betreff, nummern))
m.SetBody("text/html", result)
m.Attach(pdfort + nummern + ".pdf")
if err := mail.Send(seve, m); err != nil {
panic(err) <-- panic occurs
}
m.reset()
---Goroutine end---
I got absolutely no clues and i couldn't find anything about it anywhere.
(I also tried it with DialAndSend before)
SMTP client like thunderbird works well after TLS/SSL/STARTTLS being closed.
But can't access mailbox by github.com/go-mail/mail or github.com/go-gomail/gomail. Output same errors.
So I have this web app that has email campaigns with emails customized to individual recipients...and the average campaign per auction/claim...etc...is 35-50 recipients...I have this throttled at 6 sends per minute.
Sometimes it behaves well...other times I'll catch an email hung in 'sending'...which I set just before DialAndSend()
and set it to 'sent' right after. I added some code on my outer layers of code and the last logging output before that go routine stops responding is the log just before the DialAndSend()
as you can see in the cross-section of a log below. There's a lot of output below that point where the ==> sendMail(): No Error
or ==> sendMail(): Error: '%s'
would normally be...but it continues to hang.
It throws my Emailer service out of tilt because it doesn't respond...I'm getting ready to lay logging code into the source code I pulled so I can find exactly where it's hanging in the source code...but does anyone have any idea what might cause it to hang? Log excerpt below...at the bottom it stops and hangs.
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
===>
===> BEFORE CALL sendMail('76016 (2018 / Freightliner / Cascadia) West Blocton, Alabama')
===> START CALL sendmail('[email protected]')
m := gomail.NewMessage()
==> sendMail(): m.SetHeader("From", from.Username)
==> sendMail(): m.SetHeader("To", to)
==> sendMail(): m.SetHeader("Subject", subj)
==> BEFORE sendMail(): attachments
==> AFTER sendMail(): attachments
==> sendMail(): m.SetBody("text/html", body)
==> sendMail(): d := gomail.NewDialer(
==> sendMail(): err := d.DialAndSend(m)
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
==> sendMail(): No Error
===> END CALL sendmail('[email protected]')
===> AFTER CALL sendMail('76016 (2018 / Freightliner / Cascadia) West Blocton, Alabama')
===>
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: auction_isopen='YES'
===>
===> BEFORE CALL sendMail('76016 (2018 / Freightliner / Cascadia) West Blocton, Alabama')
===> START CALL sendmail('[email protected]')
m := gomail.NewMessage()
==> sendMail(): m.SetHeader("From", from.Username)
==> sendMail(): m.SetHeader("To", to)
==> sendMail(): m.SetHeader("Subject", subj)
==> BEFORE sendMail(): attachments
==> AFTER sendMail(): attachments
==> sendMail(): m.SetBody("text/html", body)
==> sendMail(): d := gomail.NewDialer(
==> sendMail(): err := d.DialAndSend(m)
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: comment_subjectguid = UNHEX('37e8015f2f594885b2b1bdf8416319f0')
incoming filterBy: none
incoming filterBy: auction_guid = UNHEX('d45a01b309d54223b238c59caccbdc58')
incoming filterBy: auction_guid=UNHEX('d45a01b309d54223b238c59caccbdc58')
incoming filterBy: payment_guid=UNHEX('38141d2beae046fc8d57f2eb513eb94a')
type file struct { ... }
is unexported. This means that clients cannot define their own file
s, nor even FileSetting
s.
This makes it hard to add small attachments, e.g. vCards.
The workaround is to write every attachment to a temporary file. But this is painful because it's wasteful and it needs extra cleanup code.
Far better would be to export type file
as File
.
Hi!
I managed to get the NOOP method into net/smtp
(golang/go#22321) and it looks like it will be part of Go v1.10*.
I would like to use it to improve connection handling here. My current thinking is to use the NOOP periodically and/or before trying to send a mail and re-dial a number of times if the connection broke.
How does this sound?
Another open question would be how to make this backwards compat. I imagine a checkConnection() bool
or something to hide the implementation detail so that builds pre-1.10 don't break.
(I pushed a very rough first draft to my useNOOP
branch. You can compare next..useNOOP here. It's not functional yet but I wanted to see how it could fit into the current design.)
Hello,
i dont get how I can use the NetDialTimeout to set a custom Dial Function
Thanks
Support go module versioning conventions and when used don't redirect to gopkg.in/mail.v2
https://github.com/golang/go/wiki/Modules#semantic-import-versioning
I can see that @ivy is still active on GitHub, but still, nothing has been committed on this repository for almost one year.
As this fork has been described as "Actively maintained fork of gomail", I would like to know if this project is still going to be maintained.
If not, is there any maintained and viable fork?
Sincerely,
Charles
Is there any possibility? that we can use "template view" file for
m.SetBody("text/html", "....view file.. path here"
Thanks
There is currently no support for package versioning using go mod.
Could this be added please ?
The connection deadline is only set after smtpNewClient
was called. Since smtpNewClient
already wants to read 220
from the connection, a server that does not respond will result in a hanging connection.
This issue should be resolvable by moving the deadline code just after creation of the connection.
func (d *Dialer) Dial() (SendCloser, error) {
conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), d.Timeout)
if err != nil {
return nil, err
}
if d.SSL {
conn = tlsClient(conn, d.tlsConfig())
}
c, err := smtpNewClient(conn, d.Host)
if err != nil {
return nil, err
}
if d.Timeout > 0 {
conn.SetDeadline(time.Now().Add(d.Timeout))
}
Lines 98 to 105 in 1e5036a
This code only tries to upgrade to a TLS connection if the server reports that it supports the STARTTLS extension. If an attacker intercepts the SMTP connection and responds that the extension is unknown, then they can prevent TLS from being turned on.
It would be backwards incompatible to expect STARTTLS by default, but we can make an option that would enforce a STARTTLS connection.
Of course, if the connection is already protected by SSL, then STARTTLS is unnecessary.
Hi,
I have a need to be able to add attachments from memory and not from disk. Is there any way to achieve that currently?
If not, I'm happy to implement an alternative Message.Attach that uses an io.Reader
I can send an email smoothly with html5 template as:
t, _ := template.ParseFiles("template.html")
m.AddAlternativeWriter("text/html", func(w io.Writer) error {
return t.Execute(w, struct {
Name string
Message string
Number string
}{
Name: PushName,
Message: caption,
Number: sender,
})
})
What I'm looking for, is instead of sending the template as the email body, I want to send it as attachement, something like:
m.Attach(("text/html", func(w io.Reader) error {
return t.Execute(w, struct {
Name string
Message string
Number string
}{
Name: PushName,
Message: caption,
Number: sender,
})
})
What is the best way to do so.
Thanks
Is there any way to force unencrypted connections to work?
I have tried:
.SSL = false
.StartTLSPolicy = mail.NoStartTLS
.TLSConfig = &tls.Config{InsecureSkipVerify: true}// (which was working before last update)
but nothing working now
There should be a SetBodyWriter()
method that mirrors addAlternativeWriter()
:
func (m *Message) SetBodyWriter(
contentType string, f func(io.Writer) error, settings ...PartSetting)
This is so that it's easy to use text/template or html/template to render the mail body. Otherwise, we have to create a bytes.Buffer
to hold the rendered version.
Just like SetBody
, it should clobber all existing parts.
Git tags need a v
prefix to be recognized as a Go module version
See: golang/go#24007 (comment)
e.g. for version 2.3.0
, the git tag should be v2.3.0
As it is now, we only make this attempt when the SMTP client exceeds it's configured read/write deadline. Unfortunately, this feature's been mistaken to also handle server-side timeouts (i.e., when the server disconnects an idle client). I'm sorry to say, that's not a goal of this project as SMTP servers differ too greatly for it to be maintainable (see #15 (comment)).
I believe it was a mistake to have implemented this feature in the first place and I'd like to deprecate it. Instead, users of this library should not rely on this functionality and ensure they're properly checking delivery errors and redialing. Before making any changes, I'd like to leave this issue open to allow some feedback.
gomail
to mail
v1
branch package to mail
v2
branch package to mail
v2
(stable) the default branchIs there a way to send a mail without authentication?
We use an internal exchange which allows us to send mails without providing any username and password.
I tried several ways like leaving username and password blank at NewDialer and the NoAuth Example in the docs. Both does not work.
Hi all
I've been using this package a while and have been getting the connection timeout issues for a good while. I see lots of other reports about it. But there has been no new releases of this library since 2018 even with a PR available as a fix.
I think having one or two people besides @ivy is important at this stage as the project is used in several projects, already does it's job pretty well, but will need ongoing maintenance with new go versions or as bugs are discovered.
@ivy is there someone you can think of who could do this already? I'd be willing to volunteer to review incoming PR's and issues if you don't have someone.
The following pull requests need to be reviewed and merged:
Any help getting these merged in is much appreciated!
what do you think about add ability to sing message with dkim?
When I set sender name to header on russian lang
msg.SetHeader("From", "Владимир Путин <[email protected]>")
have error gomail: could not send email 1: gomail: invalid address "=?UTF-8?q?=D0=92=D0=B5=D1=80=D0=B0_=D0=91=D0=BE=D0=B3=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2_<[email protected]>?=": mail: expected single address, got "?="
How I can do this fix?
There are some open pull requests that make changes to public interfaces:
Attach
/AttachFile
and Embed
/EmbedFile
methods.@pedromorgan: Could we make a next
branch where we can stage these changes for a future v3
release branch?
I attached a file to a message with the instruction ˋm.Attach(filename)ˋ, but there was no file with that name. The DialAndSend
instruction was aborted with a segmentation fault error. I expect to get an error message instead. The file name was for a png file in case it matters.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.