'Golang timedout sending emails

I have 708 companies whom I need to send email with login and password for authorization on my Company new web-app, where they can see statistics and other information co-working with our Company. Issue is smtp host we're using set bottleneck on sending emails 30 mail on a minute. And I realy can't think of a good way how to work with this.

I probable need use goroutine with for loop.

 import "gopkg.in/gomail.v2"

 const (
    FROM      = "[email protected]"
    PASSWORD  = "bar"
    SMTP_HOST = "smtp.google.com"
    SMTP_PORT = 465
 )

 type SendEmail struct {
    To      string
    Subject string
    Msg     string
 }

 func (se *SendEmail) Send() error{
    m := gomail.NewMessage()
    m.SetHeader("From", FROM)
    m.SetHeader("To", se.To)
    m.SetHeader("Subject", se.Subject)
    m.SetBody("text/html", se.Msg)
    d := gomail.NewDialer(SMTP_HOST, SMTP_PORT, FROM, PASSWORD)

    // Send the email
    if err := d.DialAndSend(m); err != nil {
        return err
    }

    return nil
 }

 type Company struct{
  Email string
  Login string
  Password string
 }

 func SendNotificartion(companys []Company){
  // Send 30 mail every minute
  
  for _, company := range companys {
   var send SendEmail
   send.To = company.Email
   send.Subject = "Some subject"
   send.Msg = fmt.Sprintf("Your login:%s and password:%s", company.Login, company.Password)

   if err := send.Send(); err != nil{
    log.Println(err)
   }
  }
 }


Solution 1:[1]

You can just put here pause for 1 minute, before sending another 30 pack

 func SendNotificartion(companys []Company){
  // Send 30 mail every minute
  var counter = 0
  for _, company := range companys {
   var send SendEmail
   send.To = company.Email
   send.Subject = "Some subject"
   send.Msg = fmt.Sprintf("Your login:%s and password:%s", company.Login, company.Password)

   if err := send.Send(); err != nil{
    log.Println(err)
   }
   counter++
   if counter == 30 {
       counter = 0
       time.Sleep(1 * time.Minute)
   }
  }

Solution 2:[2]

The async i/o operator is designed for this scenario. It's a better starting point than a map.

There's also been recent work done to develop a generic async sink, see FLIP-171. This has been merged into master and will be released as part of Flink 1.15.

One of those should be your best way forward. Whatever you do, don't do blocking i/o in your user functions. That causes backpressure and often leads to performance problems and checkpoint failures.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Rhidians
Solution 2