123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- package smtpn
- /*
- SMTP Notifaiction Agent
- This is the mail sending agent for sending notification to user
- */
- import (
- "encoding/json"
- "errors"
- "io/ioutil"
- "log"
- "net/smtp"
- "strconv"
- "time"
- "github.com/valyala/fasttemplate"
- notification "imuslab.com/arozos/mod/notification"
- )
- type Agent struct {
- Hostname string `json:"-"`
- SMTPSenderDisplayName string
- SMTPSender string
- SMTPPassword string
- SMTPDomain string
- SMTPPort int
- UsernameToEmail func(string) (string, error) `json:"-"`
- }
- func NewSMTPNotificationAgent(hostname string, configFile string, usernameToEmailFunction func(string) (string, error)) (*Agent, error) {
- config, err := ioutil.ReadFile(configFile)
- if err != nil {
- return nil, errors.New("Unable to load config from file: " + err.Error())
- }
- //Pasre the json file to agent object
- newAgent := Agent{}
- err = json.Unmarshal(config, &newAgent)
- if err != nil {
- return nil, errors.New("Unable to parse config file for SMTP authentication")
- }
- newAgent.Hostname = hostname
- newAgent.UsernameToEmail = usernameToEmailFunction
- return &newAgent, nil
- }
- //Generate an empty config filepath
- func GenerateEmptyConfigFile(configFilepath string) error {
- demoConfig := Agent{}
- //Stringify the empty struct
- js, err := json.MarshalIndent(demoConfig, "", " ")
- if err != nil {
- return err
- }
- //Write to file
- err = ioutil.WriteFile(configFilepath, js, 0775)
- return err
- }
- func (a Agent) Name() string {
- return "smtpn"
- }
- func (a Agent) Desc() string {
- return "Notify user throught email"
- }
- func (a Agent) IsConsumer() bool {
- return true
- }
- func (a Agent) IsProducer() bool {
- return false
- }
- func (a Agent) ConsumerNotification(incomingNotification *notification.NotificationPayload) error {
- //Get a notification and send it out
- //Analysis the notification, get the target user's email
- userEmails := [][]string{}
- for _, username := range incomingNotification.Receiver {
- userEmail, err := a.UsernameToEmail(username)
- if err == nil {
- userEmails = append(userEmails, []string{username, userEmail})
- } else {
- log.Println("[SMTP Notification] Unable to notify " + username + ": Email not set")
- }
- }
- //For each user, send out the email
- for _, thisEntry := range userEmails {
- thisUser := thisEntry[0]
- thisEmail := thisEntry[1]
- //Load email template
- template, _ := ioutil.ReadFile("system/www/smtpn.html")
- t := fasttemplate.New(string(template), "{{", "}}")
- s := t.ExecuteString(map[string]interface{}{
- "receiver": "Hello " + thisUser + ",",
- "message": incomingNotification.Message,
- "sender": incomingNotification.Sender,
- "hostname": a.Hostname,
- "timestamp": time.Now().Format("2006-01-02 3:4:5 PM"),
- })
- msg := []byte("To: " + thisEmail + "\n" +
- "From: " + a.SMTPSenderDisplayName + " <" + a.SMTPSender + ">\n" +
- "Subject: " + incomingNotification.Title + "\n" +
- "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n" +
- s + "\n\n")
- //Login to the SMTP server
- auth := smtp.PlainAuth("", a.SMTPSender, a.SMTPPassword, a.SMTPDomain)
- err := smtp.SendMail(a.SMTPDomain+":"+strconv.Itoa(a.SMTPPort), auth, a.SMTPSender, []string{thisEmail}, msg)
- if err != nil {
- log.Println("[SMTPN] Email sent failed: ", err.Error())
- return err
- }
- }
- return nil
- }
- func (a Agent) ProduceNotification(producerListeningEndpoint *notification.AgentProducerFunction) {
- return
- }
|