Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

golang net/smtp getting smtp server response DSN

Tags:

email

go

smtp

I am using golang net/smtp to send mails

Whenever I send to my smtp server I need to capture the response from the server Especially the DSN

For example my local smtp server gives a "ok queued as " at the end of the mail

I need to capture this and print in the logs

How can I do this

package main

import (
    "log"
    "net/smtp"
)

func sendEmail(msg []byte) {
    c, err := smtp.Dial("localhost:25")
    if err != nil {
        log.Fatal(err)
    }
    if err := c.Mail("[email protected]"); err != nil {
        log.Fatal(err)
    }

    if err := c.Rcpt("[email protected]"); err != nil {
        log.Fatal(err)
    }
    wc, err := c.Data()
    if err != nil {
        log.Fatal(err)
    }

    _, err = wc.Write(msg)
    if err != nil {
        log.Fatal(err)
    }

    //How do I get the response here ??
    err = wc.Close()
    if err != nil {
        log.Fatal(err)
    }

    err = c.Quit()
    if err != nil {
        log.Fatal(err)
    }
}
like image 553
Ram Avatar asked Oct 14 '18 16:10

Ram


2 Answers

As mentioned in the comments you can use c.Text.ReadResponse():

package main

import (
    "net/smtp"
)

func sendEmail(msg []byte) (code int, message string, err error) {
    c, err := smtp.Dial("localhost:25")
    if err != nil {
        return
    }
    defer c.Quit() // make sure to quit the Client

    if err = c.Mail("[email protected]"); err != nil {
        return
    }

    if err = c.Rcpt("[email protected]"); err != nil {
        return
    }

    wc, err := c.Data()
    if err != nil {
        return
    }
    defer wc.Close() // make sure WriterCloser gets closed

    _, err = wc.Write(msg)
    if err != nil {
        return
    }

    code, message, err = c.Text.ReadResponse(0)
    return
}

The code, message and any err are now passed to the caller, don't use log.Fatal throughout your code, handle the error on the calling side.

like image 115
Kevin Sandow Avatar answered Sep 29 '22 05:09

Kevin Sandow


package main

import (
    "net/smtp"
)

func sendEmail(msg []byte) (code int, message string, err error) {
    c, err := smtp.Dial("localhost:25")
    if err != nil {
        return
    }
    defer c.Quit() // make sure to quit the Client

    if err = c.Mail("[email protected]"); err != nil {
        return
    }

    if err = c.Rcpt("[email protected]"); err != nil {
        return
    }

    wc, err := c.Data()
    if err != nil {
        return
    }

    _, err = wc.Write(msg)
    if err != nil {
        return
    }

    code, message, err = closeData(c) 
    if err != nil {
        return 0, "", err
    }
    
    return code, message, err
}


func closeData(client *smtp.Client) error {
    d := &dataCloser{
        c:           client,
        WriteCloser: client.Text.DotWriter(),
    }

    return d.Close()
}

type dataCloser struct {
    c *smtp.Client
    io.WriteCloser
}

func (d *dataCloser) Close() (int, string, error) {
    d.WriteCloser.Close() // make sure WriterCloser gets closed
    code, message, err := d.c.Text.ReadResponse(250)

    fmt.Printf("Message %v, Error %v\n", message, err)
    return code, message, err
} 
like image 21
SE.Floki Avatar answered Sep 29 '22 07:09

SE.Floki