github.com/goravel/framework@v1.13.9/mail/application.go (about)

     1  package mail
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"net/smtp"
     7  
     8  	"github.com/jordan-wright/email"
     9  
    10  	"github.com/goravel/framework/contracts/config"
    11  	"github.com/goravel/framework/contracts/mail"
    12  	queuecontract "github.com/goravel/framework/contracts/queue"
    13  )
    14  
    15  type Application struct {
    16  	clone    int
    17  	config   config.Config
    18  	content  mail.Content
    19  	from     mail.From
    20  	queue    queuecontract.Queue
    21  	attaches []string
    22  	bcc      []string
    23  	cc       []string
    24  	to       []string
    25  }
    26  
    27  func NewApplication(config config.Config, queue queuecontract.Queue) *Application {
    28  	return &Application{
    29  		config: config,
    30  		queue:  queue,
    31  	}
    32  }
    33  
    34  func (r *Application) Content(content mail.Content) mail.Mail {
    35  	instance := r.instance()
    36  	instance.content = content
    37  
    38  	return instance
    39  }
    40  
    41  func (r *Application) From(from mail.From) mail.Mail {
    42  	instance := r.instance()
    43  	instance.from = from
    44  
    45  	return instance
    46  }
    47  
    48  func (r *Application) To(to []string) mail.Mail {
    49  	instance := r.instance()
    50  	instance.to = to
    51  
    52  	return instance
    53  }
    54  
    55  func (r *Application) Cc(cc []string) mail.Mail {
    56  	instance := r.instance()
    57  	instance.cc = cc
    58  
    59  	return instance
    60  }
    61  
    62  func (r *Application) Bcc(bcc []string) mail.Mail {
    63  	instance := r.instance()
    64  	instance.bcc = bcc
    65  
    66  	return instance
    67  }
    68  
    69  func (r *Application) Attach(files []string) mail.Mail {
    70  	instance := r.instance()
    71  	instance.attaches = files
    72  
    73  	return instance
    74  }
    75  
    76  func (r *Application) Send() error {
    77  	return SendMail(r.config, r.content.Subject, r.content.Html, r.from.Address, r.from.Name, r.to, r.cc, r.bcc, r.attaches)
    78  }
    79  
    80  func (r *Application) Queue(queue *mail.Queue) error {
    81  	job := r.queue.Job(NewSendMailJob(r.config), []queuecontract.Arg{
    82  		{Value: r.content.Subject, Type: "string"},
    83  		{Value: r.content.Html, Type: "string"},
    84  		{Value: r.from.Address, Type: "string"},
    85  		{Value: r.from.Name, Type: "string"},
    86  		{Value: r.to, Type: "[]string"},
    87  		{Value: r.cc, Type: "[]string"},
    88  		{Value: r.bcc, Type: "[]string"},
    89  		{Value: r.attaches, Type: "[]string"},
    90  	})
    91  	if queue != nil {
    92  		if queue.Connection != "" {
    93  			job.OnConnection(queue.Connection)
    94  		}
    95  		if queue.Queue != "" {
    96  			job.OnQueue(queue.Queue)
    97  		}
    98  	}
    99  
   100  	return job.Dispatch()
   101  }
   102  
   103  func (r *Application) instance() *Application {
   104  	if r.clone == 0 {
   105  		return &Application{
   106  			clone:  1,
   107  			config: r.config,
   108  			queue:  r.queue,
   109  		}
   110  	}
   111  
   112  	return r
   113  }
   114  
   115  func SendMail(config config.Config, subject, html string, fromAddress, fromName string, to, cc, bcc, attaches []string) error {
   116  	e := email.NewEmail()
   117  	if fromAddress == "" {
   118  		e.From = fmt.Sprintf("%s <%s>", config.GetString("mail.from.name"), config.GetString("mail.from.address"))
   119  	} else {
   120  		e.From = fmt.Sprintf("%s <%s>", fromName, fromAddress)
   121  	}
   122  
   123  	e.To = to
   124  	if len(e.Bcc) > 0 {
   125  		e.Bcc = bcc
   126  	}
   127  	if len(e.Cc) > 0 {
   128  		e.Cc = cc
   129  	}
   130  	e.Subject = subject
   131  	e.HTML = []byte(html)
   132  
   133  	for _, attach := range attaches {
   134  		if _, err := e.AttachFile(attach); err != nil {
   135  			return err
   136  		}
   137  	}
   138  
   139  	port := config.GetInt("mail.port")
   140  	switch port {
   141  	case 465:
   142  		return e.SendWithTLS(fmt.Sprintf("%s:%d", config.GetString("mail.host"), config.GetInt("mail.port")),
   143  			LoginAuth(config.GetString("mail.username"), config.GetString("mail.password")),
   144  			&tls.Config{ServerName: config.GetString("mail.host")})
   145  	case 587:
   146  		return e.SendWithStartTLS(fmt.Sprintf("%s:%d", config.GetString("mail.host"), config.GetInt("mail.port")),
   147  			LoginAuth(config.GetString("mail.username"), config.GetString("mail.password")),
   148  			&tls.Config{ServerName: config.GetString("mail.host")})
   149  	default:
   150  		return e.Send(fmt.Sprintf("%s:%d", config.GetString("mail.host"), port),
   151  			LoginAuth(config.GetString("mail.username"), config.GetString("mail.password")))
   152  	}
   153  }
   154  
   155  type loginAuth struct {
   156  	username, password string
   157  }
   158  
   159  func LoginAuth(username, password string) smtp.Auth {
   160  	return &loginAuth{username, password}
   161  }
   162  
   163  func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
   164  	return "LOGIN", []byte(a.username), nil
   165  }
   166  
   167  func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
   168  	if more {
   169  		switch string(fromServer) {
   170  		case "Username:":
   171  			return []byte(a.username), nil
   172  		case "Password:":
   173  			return []byte(a.password), nil
   174  		}
   175  	}
   176  	return nil, nil
   177  }