Giter Club home page Giter Club logo

go-smtp's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-smtp's Issues

Exceeding MaxMessageBytes causes connection to 'hang'

There's some odd behavior happening with MaxMessageBytes being exceeded.

s := smtp.NewServer(be)
s.Addr = ":2345"
s.Domain = hostname
s.AuthDisabled = true
s.MaxMessageBytes = 2
log.Fatal(server.ListenAndServe())

When I exceed the maximum message size, four very peculiar things happen:

  1. when a new line is sent, the server immediately returns a 250 OK once the message limit has been reached
  2. the connection continues to expect the terminating <CR><LF>.<CR><LF> sequence
  3. when the sequence is sent, there is no indication the expectation has been satisfied
  4. a truncated message is queued for delivery (by virtue of no error being encountered)
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 localhost ESMTP Service Ready
EHLO localhost
250-Hello localhost
250-PIPELINING
250-8BITMIME
250-ENHANCEDSTATUSCODES
250 SIZE 2
MAIL FROM: oogali@localhost
250 2.0.0 Roger, accepting mail from <oogali@localhost>
RCPT TO: test@localhost
250 2.0.0 I'll make sure <test@localhost> gets this
DATA
354 2.0.0 Go ahead. End your data with <CR><LF>.<CR><LF>
Hello.
250 2.0.0 OK: queued
QUIT
.
QUIT
221 2.0.0 Goodnight and good luck
Connection closed by foreign host.
$ gzcat ~/inbound-mail-queue/inboundfun.136391468.gz
From oogali@localhost  Thu May 14 01:29:25 2020
Return-Path: <oogali@localhost>
X-Original-To: test@localhost
Delivered-To: test@localhost
Received: from localhost (localhost [IPv6:::1])
	by localhost (inboundfun) with ESMTP id 8B1151CCC4
	for <test@localhost>; Thu, 14 May 2020 01:29:25 +0000 (UTC)
Message-Id: <20200514012925.8B1151CCC4@localhost>
Date: Thu, 14 May 2020 01:29:25 +0000 (UTC)
From: <oogali@localhost>

He

Inetd activation

Hello,

In classical inetd activation, inetd already "Accept"s the incoming connection from client, and then passes the accepted connection to the daemon.

In that case I need to bypass the Accept() call that happens in the Serve() method (server.go line 83).

Unfortunately the handleConn method is private, so I can't call it directly.

Hence my very small feature request: rname handleConn to HandleConn :)

Thanks,
Stephane

Allow backend to return per-recipient information

e.g. success for recipient 1 and failure for recipient 2.

This is required for complete LMTP support. The client should also support this.

This could be done with a LMTPError implementing error.

i have a question

smtp server is only to send email?
if i want to have some users and password i must have some code with a mysql to manage the user?

How to send reply to same thread?

I'm get Message-ID from imap

    mr, _ := mail.CreateReader(r)
    header := mr.Header
    msgId, _ = header.MessageID()

and build new message:

    msg.SetHeader("In-Reply-To", msgId)
    msg.SetHeader("References", msgId)
    msg.SetHeader("From", login)
    msg.SetHeader("To", "[email protected]")

This email is not displayed in the correspondence thread, it is visible as a new email. How to send email in thread?

Receiving email without being logged in

Hi there,

Thanks for your work on go-imap and go-smtp! I'm attempting to use them for an email-related project, and while it seems I can use go-smtp to implement a message submission port well enough, I can't use it to accept email from the wider Internet (e.g., the kind of thing Exim usually does when configured as an internet site).

An SMTP transaction of this kind would generally look like:

EHLO example.com
MAIL FROM:...
RCPT TO:...
DATA
...
.
QUIT

Would you be willing to consider a PR that allows this behaviour to be optionally enabled? Something like:

be := mybackend.NewSubmission()
unauthenticatedBE := mybackend.NewSMTP()

server := smtp.NewServer(backend)
server.UnauthenticatedBackend = unauthenticatedBE

If the UnauthenticatedBackend is nil, we can continue to reject as we do presently. If it's set, login is optional. If a message comes through without a login happening, the UnauthenticatedBackend handles it.

We could also add:

server.LoginDisabled = true

This would disable the AUTH command completely, which would make things a bit cleaner from my side :)

Happy to do the work for this, I just wanted to open a line of communication about it before starting! Let me know.

Returning MessageId in 200 OK Response

Hi

Today when the message gets queued we send response 250 2.0.0 OK: queued. Other smtp servers returns a messageId to help the client's track the request later, eg: google does 250 2.0.0 OK 1571601091 d44si1315748ede.149 - gsmtp

How to implement the same ?

I see this option in conn.go

func (c *Conn) handleData(arg string) {
....
code, enhancedCode, msg := toSMTPStatus(c.Session().Data(r))

Split this into two

msg, err := c.Session().Data(r)
code, enhancedCode, msg := toSMTPStatus(err, msg)

But this breaks the signature of Session. What would you suggest in this? What are the other ways to achieve this?

Howto read the SMTP server response?

Hi!

How do I read the SMTP server response on smtp.SendMail ? Example: my SMTP server tell me the queue id when the email is queued (250 2.0.0 Ok: queued as C0E5C82029\n). I want to get this.

IT's possible?

Denial of service possible (DoS)

Hello,
I'm doing some testing on this package, thanks for the great work. 👍

I wanted to share with you two possible denial of service.
Right now, anybody can open a connection and keep it for ever doing :

- Bad command ( commands that are not handle by the parse() function )
c.nbrErrors++ will be incremented but will never trigger a connection close()

- Speak Up (When command is empty)
A connection can stay open , sending empty commands for ever

In both cases, the attacker can open as many connection, send either "bad commands" not parsed. So , for example, 1 char, 2char, 3 char commands or just empty commands and will never reach any disconnect.

As a quick fix, I would suggest this to evaluate the c.nbrErrors counter and disconnect if > 3
In both scenarios

Example:
File: conn.go
Line: 101

	if cmd == "" {
		c.nbrErrors++
		if c.nbrErrors > 3 {
			c.WriteResponse(500, EnhancedCode{5, 5, 2}, "Too many errors")
			c.Close()
		}	
		c.WriteResponse(500, EnhancedCode{5, 5, 2}, "Speak up")
		return
	}

file: server.go
Line: 137

	if err != nil {
		c.nbrErrors++
		if c.nbrErrors > 3 {
			c.WriteResponse(500, EnhancedCode{5, 5, 2}, "Too many errors")
			c.Close()
		}					
	
		c.WriteResponse(501, EnhancedCode{5, 5, 2}, "Bad command")
		continue
	}	

Hope this help.

Ability to return custom responses?

I'd like to return custom responses in response to the execution of the Mail, Rcpt, and Data functions of the Session object.

I see I can string together my own responses using SMTPError, however the logic in the connection handling code doesn't particularly like receiving any sort of error.

Would it be against the spirit of the project if this logic was modified to further inspect SMTPError and only error out if SMTPError.Code was not 250?

Error return value is not checked

We could check for returned errors more often :-)

client.go:225:9: Error return value of `c.Quit` is not checked 
		c.Quit()
		      
client.go:251:9: Error return value of `c.cmd` is not checked 
			c.cmd(501, "*")
			     
client.go:252:10: Error return value of `c.Quit` is not checked 
			c.Quit()
			      
client_test.go:42:8: Error return value of `c.Auth` is not checked 
	c.Auth(toServerEmptyAuth{}) 
				             
client_test.go:437:18: Error return value of `bcmdbuf.Write` is not checked 
				bcmdbuf.Write([]byte(msg + "\r\n"))
				             	             
client_test.go:633:15: Error return value of `c.Quit` is not checked 
		defer c.Quit()
		            
client_test.go:669:11: Error return value of `s.w.Write` is not checked 
	s.w.Write([]byte(f + "\r\n"))
	         
conn.go:143:17: Error return value of `session.Logout` is not checked 
		session.Logout()
		              
conn.go:439:9: Error return value of `io.Copy` is not checked 
	io.Copy(ioutil.Discard, r) // Make sure all the data has been consumed
	       
conn.go:477:26: Error return value of `c.conn.SetWriteDeadline` is not checked 
		c.conn.SetWriteDeadline(time.Now().Add(c.server.WriteTimeout))
		                       
conn.go:502:19: Error return value of `c.session.Logout` is not checked 
		c.session.Logout()
		                
server.go:91:18: Error return value of `s.handleConn` is not checked 
		go s.handleConn(newConn(c, s))
		               

Relationship with net/smtp

I'm sorry if I am reading over something, but it seems a lot of this library is exactly the same as net/smtp. What is the difference, and in which scenarios is net/smtp not sufficient? Thanks :)

RFC 3030 (CHUNKING, BINARYMIME) support

CHUNKING (BDAT) support

Client support: Prefer over DATA if available (avoids the overhead of dot-encoding), require if BODY=BINARYMIME is used (as required by spec).
Server support: Transparent support, io.Reader passed to Session.Data reads multiple chunks. Error returned by Data early consumes the current chunk and returns an error without consuming the whole message.

BINARYMIME support

Support BODY=BINARYMIME argument for MAIL command, no other actions required.

Specification: https://tools.ietf.org/html/rfc3030

Add function to get connection RemoteAddr

Hi,
it would be useful to have the remote address of the connection to implement a filter based on sender IP.
I think it could be implemented defining User struct (UserData as User is already ad interface) with RemoteAddr field filled during init of connection.

This change will impact how User is defined as at this moment the Login functions are responsible of User creation. With this change the User object is created by the connection filling all relevant data and passing it to Login functions. Is this doable?

How to Use Proxy

Thank you for your contribution!
I want to use proxy to request, But I'm not found how to use proxy!
Thank You

SMTPUTF8 capability

I believe most backend implementations could handle UTF-8 addresses and MIME headers just fine, so it is a good idea to tell clients that we are fine with UTF-8.

Also I think we should tell the backend that SMTPUTF8 support was requested (through MAIL argument). This way it can make decision on whether it can actually handle the message (say, if it implements transparent forwarding and upstream server doesn't support SMTPUTF8).

References:

554, b'5.0.0 Error: transaction failed, blame it on the weathe

how to solve this , thanks

package main

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"strings"
	"time"

	"github.com/emersion/go-sasl"
	"github.com/emersion/go-smtp"
)

type Backend struct{}

// Login handles a login command with username and password.
func (bkd *Backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
	if username != "username" || password != "password" {
		return nil, errors.New("Invalid username or password")
	}
	return &Session{
		to: make([]string, 0),
	}, nil
}

// AnonymousLogin requires clients to authenticate using SMTP AUTH before sending emails
func (bkd *Backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
	return nil, smtp.ErrAuthRequired
}

// A Session is returned after successful login.
type Session struct {
	to   []string
	from string
	data []byte
}

func (s *Session) Mail(from string, opts smtp.MailOptions) error {
	s.from = from
	log.Println("Mail from:", from)
	return nil
}

func (s *Session) Rcpt(to string) error {
	for _, v := range strings.Split(to, ",") {
		t := strings.Trim(v, " ")
		s.to = append(s.to, t)
	}
	log.Println("Rcpt to:", to)
	return nil
}

func (s *Session) Data(r io.Reader) error {
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}
	log.Println("Data:", string(b))

	for _, user := range s.to {
		u := strings.Split(user, "@")
		host := "smtp." + u[1] + ":465"
		auth := sasl.NewPlainClient("", "", "")
		err = smtp.SendMail(host, auth, s.from, []string{user}, r)
		if err != nil {
			fmt.Println(err)
			return err
		}

	}

	return nil
}

func (s *Session) Reset() {}

func (s *Session) Logout() error {
	return nil
}

func main() {
	be := &Backend{}

	s := smtp.NewServer(be)

	s.Addr = ":1025"
	s.Domain = "smtp.hyahm.com"
	s.ReadTimeout = 10 * time.Second
	s.WriteTimeout = 10 * time.Second
	s.MaxMessageBytes = 1024 * 1024
	s.MaxRecipients = 50
	s.AllowInsecureAuth = true

	log.Println("Starting server at", s.Addr)
	if err := s.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

client

#!/usr/bin/python3
 
import smtplib
from email.mime.text import MIMEText
from email.header import Header
 
# 第三方 SMTP 服务
mail_host="smtp.hyahm.com"  #设置服务器
mail_user="username"    #用户名
mail_pass="password"   #口令 
 
 
sender = '[email protected]'
receivers = ['[email protected]']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
 
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] =  Header("测试", 'utf-8')
 
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
 
 
try:
    smtpObj = smtplib.SMTP() 
    smtpObj.connect(mail_host, 1025)    # 25 为 SMTP 端口号
    smtpObj.login(mail_user,mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print ("邮件发送成功")
except smtplib.SMTPException as e:
    print(e)
    print ("Error: 无法发送邮件")

error message

(554, b'5.0.0 Error: transaction failed, blame it on the weather: EOF')

client: Add I/O timeouts

RFC 5321:

4.5.3.2. Timeouts

An SMTP client MUST provide a timeout mechanism. It MUST use per-
command timeouts rather than somehow trying to time the entire mail
transaction. Timeouts SHOULD be easily reconfigurable, preferably
without recompiling the SMTP code.

MAIL in Strict mode doesn't support optional extensions

It looks like the MAIL parsing in strict mode expects the only argument to be the FROM argument, but the SMTP spec allows for optional mail-parameters that are associated with service extensions. See https://tools.ietf.org/html/rfc5321#section-3.3.

It might be safe to ignore these parameters, but right now the server returns a 501 because it expects the argument to end with a >.

Example command from the client:

MAIL FROM:<[email protected]> AUTH=<username>

Response from go-smtp:

501 Was expecting MAIL arg syntax of FROM:<address>

It seems like KMail includes these additional parameters (see https://www.reddit.com/r/ProtonMail/comments/evadaz/need_help_setting_up_outgoing_with_kmail/), as well as emailrelay.

Enhanced Status Codes support

  • Add EnhancedCode field to SMTPError ([3]uint?)
  • Client: Parse enhanced codes
  • Server: Add capability "ENHANCEDSTATUSCODES" (#37)
  • Server: Set X.0.0 (X is based on class) if returned error lacks explicit code
  • Server: Send enhanced codes (#37)

Fix example server

.\sm.go:17:34: undefined: smtp.ConnectionState
.\sm.go:17:84: undefined: smtp.Session
.\sm.go:25:43: undefined: smtp.ConnectionState
.\sm.go:25:66: undefined: smtp.Session
.\sm.go:38:26: undefined: from
.\sm.go:64:3: s.ReadTimeout undefined (type *smtp.Server has no field or method ReadTimeout)
.\sm.go:65:3: s.WriteTimeout undefined (type *smtp.Server has no field or method WriteTimeout)

Can not receive mail

Can not receive mail

server.go

package main

import (
	"errors"
	"io"
	"io/ioutil"
	"log"
	"time"

	"github.com/emersion/go-smtp"
)

type Backend struct{}

// Login handles a login command with username and password.
func (bkd *Backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
	if username != "username" || password != "password" {
		return nil, errors.New("Invalid username or password")
	}
	return &Session{}, nil
}

// AnonymousLogin requires clients to authenticate using SMTP AUTH before sending emails
func (bkd *Backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
	return nil, smtp.ErrAuthRequired
}

// A Session is returned after successful login.
type Session struct{}

func (s *Session) Mail(from string, opts smtp.MailOptions) error {
	log.Println("Mail from:", from)
	return nil
}

func (s *Session) Rcpt(to string) error {
	log.Println("Rcpt to:", to)
	return nil
}

func (s *Session) Data(r io.Reader) error {
	if b, err := ioutil.ReadAll(r); err != nil {
		return err
	} else {
		log.Println("Data:", string(b))
	}
	return nil
}

func (s *Session) Reset() {}

func (s *Session) Logout() error {
	return nil
}

func main() {
	be := &Backend{}

	s := smtp.NewServer(be)

	s.Addr = ":1025"
	s.Domain = "localhost"
	s.ReadTimeout = 10 * time.Second
	s.WriteTimeout = 10 * time.Second
	s.MaxMessageBytes = 1024 * 1024
	s.MaxRecipients = 50
	s.AllowInsecureAuth = true

	log.Println("Starting server at", s.Addr)
	if err := s.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

client.py

#!/usr/bin/python3
 
import smtplib
from email.mime.text import MIMEText
from email.header import Header
 
# 第三方 SMTP 服务
mail_host="smtp.hyahm.com"  #设置服务器
mail_user="username"    #用户名
mail_pass="password"   #口令 
 
 
sender = '[email protected]'
receivers = ['[email protected]']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
 
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] =  Header("测试", 'utf-8')
 
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
 
 
try:
    smtpObj = smtplib.SMTP() 
    smtpObj.connect(mail_host, 1025)    # 25 为 SMTP 端口号
    smtpObj.login(mail_user,mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print ("邮件发送成功")
except smtplib.SMTPException as e:
    print(e)
    print ("Error: 无法发送邮件")
[root@cander test]# python testemail.py 
邮件发送成功

server output

2020/01/06 15:23:44 Mail from: [email protected]
2020/01/06 15:23:44 Rcpt to: [email protected]
2020/01/06 15:23:44 Data: Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
From: =?utf-8?b?6I+c6bif5pWZ56iL?=
To: =?utf-8?b?5rWL6K+V?=
Subject: =?utf-8?b?UHl0aG9uIFNNVFAg6YKu5Lu25rWL6K+V?=

UHl0aG9uIOmCruS7tuWPkemAgea1i+ivlS4uLg==

Comparison Benchmark

Brad's original https://github.com/bradfitz/go-smtpd was forked by https://github.com/mhale/smtpd who (with help) added a lot of RFC compliance and general updates. They don't have streaming support so I forked the project again and made https://github.com/Xeoncross/smtpd. I actually ended up rewriting a lot of it to remove code better handled by the stdlib.

I went ahead and benchmarked this repo against mine after realizing @emersion had basically made all the same design decisions (using textproto instead of manual string/byte checking) and it seems you have done a better job again.

Here you can see BenchmarkNetSMTP (mine) against BenchmarkEmersionGoSMTP (yours) with a basic 2k multipart/MIME email body read to ioutil.Discard.

go test -bench=. --benchmem                    
goos: darwin
goarch: amd64
BenchmarkRawProcessingSequence-8   	   20000	     63182 ns/op	   34595 B/op	      68 allocs/op
BenchmarkNetSMTP-8                 	    2000	    717042 ns/op	  128394 B/op	     338 allocs/op
BenchmarkEmersionGoSMTP-8          	    3000	    517125 ns/op	   68882 B/op	     292 allocs/op

(Note: BenchmarkRawProcessingSequence is just a net.Pipe() with no actual sockets or TCP overhead for comparison.)

Thanks again for your work on all these email libraries.

start a simple server

I just copy the example codes , a server and a client and trying to send a test email.
the server outputs :
`
2020/01/29 17:30:45 Starting server at :1025
2020/01/29 17:31:19 Mail from: [email protected]
2020/01/29 17:31:19 Rcpt to: [email protected]
2020/01/29 17:31:19 Data: To: [email protected]
Subject: discount Gophers!

This is the email body.
`
but i just didn't receive any email.
would you please help me with that.

Implement AUTH LOGIN method

Some thoughts on adding server support for this.

The server code already supports the PLAIN method described in https://tools.ietf.org/html/rfc4954#section-4.1
however https://tools.ietf.org/html/rfc4422#section-3 is also relevant.

Client swaks is liberal in using whichever PLAIN or LOGIN auth methods the server offers.
Some clients (e.g. Windows PowerShell Send-MailMessage) cannot use PLAIN (according to tests I've tried).

Adding a sasl.Login entry to func NewServer in server.go achieves most of what's needed. Then we interwork with clients such as swaks.
This is because swaks chooses to send the basic LOGIN command form (without username) then await the server's challenge response.

Aforementioned Windows client chooses to always send the LOGIN base64username form. This is not currently handled by go-sasl/login.go func Next, because it always begins in the loginNotStarted state, ignoring the already provided username, and proceeds to challenge for it.

https://github.com/emersion/go-sasl/blob/7e096a0a6197b89989e8cc31016daa67c8c62051/login.go#L32

Ideally we support both LOGIN formats. I'm happy to do the work. I just had a question of style for you -

a) make go-sasl/login.go Next be aware of the presence of an initial response value, assume this is the username, and go straight to loginWaitingPassword

or
b) add conditional logic to

go-smtp/conn.go

Line 359 in 469c269

response := ir
to explicitly call Next one time before entering the for loop

b) limits scope of change to just this repo; but perhaps it's better to improve Next to handle RFC4422 sec 3 fully.

See also
https://www.jetmore.org/john/code/swaks/latest/doc/ref.txt
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-6

minor release needed

hello, I would like to recommend that a minor release be made. From reading about the 2 commits besides the README tweaks since the last release, I see that there is both a race condition as well as a security issue fixed. Are there any other steps that need to be taken first? PR 72 also looks pretty critical to merge, though I see it shows a failed status due to a very small decrease in code coverage. It would be great to see that slip into the patch release.

Very restrictive MAIL FROM

Most SMTP servers I've used allow MAIL FROM: user@host. I've never used one that required MAIL FROM:<user@host>.

I note that the parsing for RCPT TO: is far more forgiving - stripping the <> chars from the trailing text.

Can I submit a PR to make this strict parsing an option?

Context support

Adding context support would be nice for tracing and cancellation.

Thanks for this library!

SMTP server: panic: runtime error: index out of range

I've done some fuzzing and found one crash:
(parts of paths are replaced to xxxx)

goroutine 1 [running]:
github.com/emersion/go-smtp.(*Conn).handleAuth(0xc000366070, 0xc00036f8ed, 0x1)
	/home/user/Documents/xxxx/src/github.com/emersion/go-smtp/conn.go:339 +0x97a
github.com/emersion/go-smtp.(*Conn).handle(0xc000366070, 0xc00036f8e8, 0x4, 0xc00036f8ed, 0x1)
	/home/user/Documents/xxxx/src/github.com/emersion/go-smtp/conn.go:115 +0x180
github.com/emersion/go-smtp.(*Server).handleConn(0xc0000c38c0, 0xc000366070, 0x0, 0x0)
	/home/user/Documents/xxxx/src/github.com/emersion/go-smtp/server.go:122 +0x287
github.com/emersion/go-smtp.(*Server).Serve(0xc0000c38c0, 0x649ac0, 0xc0000acc40, 0x0, 0x0)
	/home/user/Documents/xxxx/src/github.com/emersion/go-smtp/server.go:93 +0xf2
fuzz/fuzzsmtpserver.Fuzz(0x7408aa0f7000, 0xd, 0x200000, 0x3)
	/home/user/Documents/xxxx/src/fuzz/fuzzsmtpserver/fuzz.go:63 +0x262
go-fuzz-dep.Main(0xc000046f80, 0x1, 0x1)
	/tmp/go-fuzz-build433312042/goroot/src/go-fuzz-dep/main.go:36 +0x1b6
main.main()
	/tmp/go-fuzz-build433312042/gopath/src/fuzz/fuzzsmtpserver/go.fuzz.main/main.go:15 +0x52
exit status 2

After sending to socket following data

[user@work crashers]$ cat 82fbe7cec7da6c1559d3780b7c0122064c01f1f1 | hexdump
0000000 4845 4f4c 3020 410a 5455 2048 000b     
000000d

[user@work crashers]$ cat 82fbe7cec7da6c1559d3780b7c0122064c01f1f1 | hexdump -c
0000000   E   H   L   O       0  \n   A   U   T   H      \v            
000000d

[user@work crashers]$ cat 82fbe7cec7da6c1559d3780b7c0122064c01f1f1.quoted 
	"EHLO 0\nAUTH \v"

To perform fuzzing I've modified Serve function in Server, it looks like that now:

// Serve accepts incoming connections on the Listener l.
func (s *Server) Serve(l net.Listener) error {
	s.listener = l
	defer s.Close()

	for {
		c, err := l.Accept()
		if err != nil {
			return err
		}

		// Modified for fuzzing - removed go so its synchronous now
		/* go */ s.handleConn(newConn(c, s))
	}
}

I didn't test this on base(with go s.handleConn) version nevertheless it seems like it should work on original as well.
I guess I've run go get -u before running it, someone might test that as well though.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.