Comments (18)
Here's the code of LoginAuth:
type loginAuth struct {
username, password string
}
// loginAuth returns an Auth that implements the LOGIN authentication
// mechanism as defined in RFC 4616.
func LoginAuth(username, password string) smtp.Auth {
return &loginAuth{username, password}
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "LOGIN", nil, nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
command := string(fromServer)
command = strings.TrimSpace(command)
command = strings.TrimSuffix(command, ":")
command = strings.ToLower(command)
if more {
if (command == "username") {
return []byte(fmt.Sprintf("%s", a.username)), nil
} else if (command == "password") {
return []byte(fmt.Sprintf("%s", a.password)), nil
} else {
// We've already sent everything.
return nil, fmt.Errorf("unexpected server challenge: %s", command)
}
}
return nil, nil
}
Then call: mailer := gomail.NewCustomMailer("smtp.office365.com:587", LoginAuth("[email protected]", "password"))
.
Not sure why I don't need to use base64 to decode server commands and encode user and password :/
from gomail.
You should try to use you own Auth mechanism.
Create a Login
authentication mechanism by copying PlainAuth from the standard library and replace the two instances of PLAIN
by LOGIN
.
Then use gomail.NewCustomMailer to use your new auth mechanism.
If it works I will update Gomail to automatically use the LOGIN
mechanism when PLAIN
is not available.
from gomail.
Ok, I'll ping you when I get it. Thanks!
from gomail.
Hey, I found time to work on it! :)
type loginAuth struct {
identity, username, password string
host string
}
// loginAuth returns an Auth that implements the LOGIN authentication
// mechanism as defined in RFC 4616.
// The returned Auth uses the given username and password to authenticate
// on TLS connections to host and act as identity. Usually identity will be
// left blank to act as username.
func LoginAuth(identity, username, password, host string) smtp.Auth {
return &loginAuth{identity, username, password, host}
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
if !server.TLS {
advertised := false
for _, mechanism := range server.Auth {
if mechanism == "LOGIN" {
advertised = true
break
}
}
if !advertised {
return "", nil, errors.New("unencrypted connection")
}
}
if server.Name != a.host {
return "", nil, errors.New("wrong host name")
}
resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
return "LOGIN", resp, nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
// log.Println("NEXT: ", fromServer)
if more {
// We've already sent everything.
return nil, errors.New("unexpected server challenge")
}
return nil, nil
}
Then, create mailer with this:
mailer := gomail.NewCustomMailer("smtp.office365.com:587", LoginAuth("", "[email protected]", "password", "smtp.office365.com"))
But I'm getting error from LoginAuth.Next
:
unexpected server challenge
If you see the implementation on SwiftMailer the commands sent are with different notation:
AuthPlain: https://github.com/swiftmailer/swiftmailer/blob/master/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php#L41
AuthLogin: https://github.com/swiftmailer/swiftmailer/blob/master/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php#L40
I don't know how to change this... too late :(
Can you help me? Thanks!!!
from gomail.
Ok I think the first command is just AUTH LOGIN
and then two more commands with username and password:
$agent->executeCommand("AUTH LOGIN\r\n", array(334));
$agent->executeCommand(sprintf("%s\r\n", base64_encode($username)), array(334));
$agent->executeCommand(sprintf("%s\r\n", base64_encode($password)), array(235));
So, to do this, in LoginAuth.Start
we just have to send return "LOGIN", nil, nil
and the other commands should be sent in LoginAuth.Next
right?
So, two questions, how to know if I'm sending the first (username) or second (password) parameter?
Maybe an step
parameter initialized in Start
method.
So now the question is how to encode the two commands to the server...
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
log.Println("NEXT: ", fromServer)
// if more {
// // We've already sent everything.
// return nil, errors.New("unexpected server challenge")
// }
if more {
if (a.authInit == true) {
a.authInit = false
return []byte(fmt.Sprintf("%s %x", a.username, 334)), nil
} else {
return []byte(fmt.Sprintf("%s %x", a.password, 235)), nil
}
}
return nil, nil
}
Don't know how to set the second parameter of Sprintf
. Too late for today.
from gomail.
Sorry I do not have the issue so I cannot help you much.
334 and 235 are not parameters on Sprintf but of executeCommand in the Swiftmailer code. So you should try removing them.
from gomail.
I suppose the spec needs some length or code at the end of the command:
Like http://golang.org/src/net/smtp/auth.go#L99
func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
d := hmac.New(md5.New, []byte(a.secret))
d.Write(fromServer)
s := make([]byte, 0, d.Size())
return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil
}
return nil, nil
}
I'm just asking for your help because you played with the SMTP protocol right? :)
Thanks anyway!
from gomail.
Yayyyy it works!!!
I just have to follow the spec hehe:
http://www.samlogic.net/articles/smtp-commands-reference-auth.htm
I think I will send a pull request for "net/smtp/auth.go" :) but first I need to clean up things and make some tests.
Thanks!
from gomail.
Ok, while it's accepted as a pull request (if there's a chance) how you will deal with this "bug"?
Meanwhile could be implemented in your library?
How will the NewMailer
know and use the AUTH LOGIN
mechanism?
from gomail.
Good job !
It is a bit difficult to do the fix since I cannot create an account on office365. Could you send the content of:
- the content of
server
in your functionStart
(withfmt.Printf("%#v\n", server)
for example) - the content of
fromServer
(withfmt.Printf("%s\n", server)
for example) in yourNext
function - the second variable returned by
c.Extension("AUTH")
here
from gomail.
On Start
function fmt.Printf("server(@alexcesaro): %#v\n", server)
On Next
function fmt.Printf("fromServer(@alexcesaro): %s\n", string(fromServer))
On getSendMailFunc
function fmt.Printf("SendMailFunc(@alexcesaro): %#v\n", secondParameter)
server(@alexcesaro): &smtp.ServerInfo{Name:"smtp.office365.com", TLS:true, Auth:[]string{"LOGIN"}}
fromServer(@alexcesaro): Username:
fromServer(@alexcesaro): Password:
fromServer(@alexcesaro): 2.7.0 Authentication successful target host DB3PR02MB219.eurprd02.prod.outlook.com
SendMailFunc(@alexcesaro): "LOGIN"
from gomail.
Thanks!
I commited a new function on a new branch, can you try it to see if it works? See the readme for more details.
from gomail.
Sorry for the delay! Checked that it works perfectly!!! :D 💃
Which GMail it's working with this new AuthLogin or it was working before? I assume both are using the same login mechanism.
Will you create a new version? How I have to update it?
Thanks!
from gomail.
In case it will be included in SMTP standard library.
https://groups.google.com/forum/#!topic/golang-nuts/Cr5I_J9LhSI
from gomail.
I merged the branch. You can do go get -u gopkg.in/gomail.v1
to get the new version.
Gmail works well on the PLAIN mechanism and using this new auth is not needed.
from gomail.
Perfect! Thanks a lot!
from gomail.
I landed here after receiving the error from the Go standard library net/smtp
while using smtp.office365.com
on port 587. The alternative solution from @marcalj (LoginAuth
- which implements the login as per RFC 4616) works (thanks!).
I am on Go version 1.10.3 and I am a bit surprised this issue (error/bug?) is still in there.
Is this a bug at all or more of a non-standard convention or dialect of SMTP over TLS? I can not find evidence of this kind of problem on the Go standard library.
from gomail.
from gomail.
Related Issues (20)
- panic: 454 4.7.0 TLS not available due to local problem?Does anyone know why?
- Recipient address rejected: Email Sending Quota Exceeded
- How can i set message-id before sending? HOT 1
- Incorrect behavior using html/template with AddAlternativeWriter HOT 3
- how to send to multiple recipients but they can only see themselves in the recipient field HOT 1
- Embedded image not showing in mobile devices HOT 1
- Attach PDF HOT 2
- Not receiving email when sending email as No SMTP. HOT 1
- Maintainer has left this world HOT 1
- How to set email importance and email-receipt? HOT 2
- How to download it? HOT 1
- How to send emails using SSL encryption or TLS encryption HOT 1
- Mail Delivery Subsystem Error HOT 2
- Could we add support to specifically unset/delete all attachements? HOT 2
- Where to Report Vulnerabilities? HOT 2
- Can not send email to stmp.163.com and stmp.qq.com
- Email content tampering vulnerability due to crafted file names
- [feature] Flag to ignore invalid address error HOT 2
- Email doesnt send if there is one of receipts address invalid HOT 4
- how to config ssl HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gomail.