github.com/kubevela/workflow@v0.6.0/pkg/providers/email/send.go (about)

     1  /*
     2  Copyright 2022 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package email
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  
    23  	"gopkg.in/gomail.v2"
    24  
    25  	monitorContext "github.com/kubevela/pkg/monitor/context"
    26  
    27  	wfContext "github.com/kubevela/workflow/pkg/context"
    28  	"github.com/kubevela/workflow/pkg/cue/model/value"
    29  	"github.com/kubevela/workflow/pkg/types"
    30  )
    31  
    32  const (
    33  	// ProviderName is provider name for install.
    34  	ProviderName = "email"
    35  )
    36  
    37  type provider struct {
    38  }
    39  
    40  type sender struct {
    41  	Address  string `json:"address"`
    42  	Alias    string `json:"alias,omitempty"`
    43  	Password string `json:"password"`
    44  	Host     string `json:"host"`
    45  	Port     int    `json:"port"`
    46  }
    47  
    48  type content struct {
    49  	Subject string `json:"subject"`
    50  	Body    string `json:"body"`
    51  }
    52  
    53  var emailRoutine sync.Map
    54  
    55  // Send sends email
    56  func (h *provider) Send(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
    57  	stepID, err := v.LookupValue("stepID")
    58  	if err != nil {
    59  		return err
    60  	}
    61  	id, err := stepID.String()
    62  	if err != nil {
    63  		return err
    64  	}
    65  	routine, ok := emailRoutine.Load(id)
    66  	if ok {
    67  		switch routine {
    68  		case "success":
    69  			emailRoutine.Delete(id)
    70  			return nil
    71  		case "initializing", "sending":
    72  			act.Wait("wait for the email")
    73  			return nil
    74  		default:
    75  			emailRoutine.Delete(id)
    76  			return fmt.Errorf("failed to send email: %v", routine)
    77  		}
    78  	} else {
    79  		emailRoutine.Store(id, "initializing")
    80  	}
    81  
    82  	s, err := v.LookupValue("from")
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	senderValue := &sender{}
    88  	if err := s.UnmarshalTo(senderValue); err != nil {
    89  		return err
    90  	}
    91  
    92  	r, err := v.LookupValue("to")
    93  	if err != nil {
    94  		return err
    95  	}
    96  	receiverValue := &[]string{}
    97  	if err := r.UnmarshalTo(receiverValue); err != nil {
    98  		return err
    99  	}
   100  
   101  	c, err := v.LookupValue("content")
   102  	if err != nil {
   103  		return err
   104  	}
   105  	contentValue := &content{}
   106  	if err := c.UnmarshalTo(contentValue); err != nil {
   107  		return err
   108  	}
   109  
   110  	m := gomail.NewMessage()
   111  	m.SetAddressHeader("From", senderValue.Address, senderValue.Alias)
   112  	m.SetHeader("To", *receiverValue...)
   113  	m.SetHeader("Subject", contentValue.Subject)
   114  	m.SetBody("text/html", contentValue.Body)
   115  
   116  	dial := gomail.NewDialer(senderValue.Host, senderValue.Port, senderValue.Address, senderValue.Password)
   117  	go func() {
   118  		if routine, ok := emailRoutine.Load(id); ok && routine == "initializing" {
   119  			emailRoutine.Store(id, "sending")
   120  			if err := dial.DialAndSend(m); err != nil {
   121  				emailRoutine.Store(id, err.Error())
   122  				return
   123  			}
   124  			emailRoutine.Store(id, "success")
   125  		}
   126  	}()
   127  	act.Wait("wait for the email")
   128  	return nil
   129  }
   130  
   131  // Install register handlers to provider discover.
   132  func Install(p types.Providers) {
   133  	prd := &provider{}
   134  	p.Register(ProviderName, map[string]types.Handler{
   135  		"send": prd.Send,
   136  	})
   137  }