You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: email_handler.gen.go
    path of file: ./repos/corteza/server/automation/automation
    
    the code of the file until where you have to start completion: package automation

// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// automation/automation/email_handler.yaml

import (
	"context"
	atypes "github.com/cortezaproject/corteza/server/automation/types"
	"github.com/cortezaproject/corteza/server/pkg/expr"
	"github.com/cortezaproject/corteza/server/pkg/wfexec"
	sysTypes "github.com/cortezaproject/corteza/server/system/types"
	"io"
)

var _ wfexec.ExecResponse

type (
	emailHandlerRegistry interface {
		AddFunctions(ff ...*atypes.Function)
		Type(ref string) expr.Type
	}
)

func (h emailHandler) register() {
	h.reg.AddFunctions(
		h.Send(),
		h.Message(),
		h.SendMessage(),
		h.SetSubject(),
		h.SetHeaders(),
		h.SetHeader(),
		h.SetAddress(),
		h.AddAddress(),
		h.Attach(),
		h.Embed(),
	)
}

type (
	emailSendArgs struct {
		hasSubject    bool
		Subject       interface{}
		subjectString string
		subjectStream io.Reader

		hasReplyTo    bool
		ReplyTo       interface{}
		replyToString string
		replyToUser   *sysTypes.User

		hasFrom    bool
		From       interface{}
		fromString string
		fromUser   *sysTypes.User

		hasTo    bool
		To       interface{}
		toString string
		toKV     map[string]string
		toUser   *sysTypes.User

		hasCc    bool
		Cc       interface{}
		ccString string
		ccKV     map[string]string
		ccUser   *sysTypes.User

		hasHtml    bool
		Html       interface{}
		htmlString string
		htmlStream io.Reader

		hasPlain    bool
		Plain       interface{}
		plainString string
		plainStream io.Reader
	}
)

func (a emailSendArgs) GetSubject() (bool, string, io.Reader) {
	return a.hasSubject, a.subjectString, a.subjectStream
}

func (a emailSendArgs) GetReplyTo() (bool, string, *sysTypes.User) {
	return a.hasReplyTo, a.replyToString, a.replyToUser
}

func (a emailSendArgs) GetFrom() (bool, string, *sysTypes.User) {
	return a.hasFrom, a.fromString, a.fromUser
}

func (a emailSendArgs) GetTo() (bool, string, map[string]string, *sysTypes.User) {
	return a.hasTo, a.toString, a.toKV, a.toUser
}

func (a emailSendArgs) GetCc() (bool, string, map[string]string, *sysTypes.User) {
	return a.hasCc, a.ccString, a.ccKV, a.ccUser
}

func (a emailSendArgs) GetHtml() (bool, string, io.Reader) {
	return a.hasHtml, a.htmlStri
    
func (h emailHandler) Message() *atypes.Function {
	return &atypes.Function{
		Ref:    "emailMessage",
		Kind:   "function",
		Labels: map[string]string(nil),
		Meta: &atypes.FunctionMeta{
			Short:       "Email builder",
			Description: "Constructs new email message from basic parameters without sending it",
		},

		Parameters: []*atypes.Param{
			{
				Name:  "subject",
				Types: []string{"String", "Reader"},
				Meta: &atypes.ParamMeta{
					Label: "Subject",
				},
			},
			{
				Name:  "replyTo",
				Types: []string{"String", "User"},
				Meta: &atypes.ParamMeta{
					Label: "Reply to",
				},
			},
			{
				Name:  "from",
				Types: []string{"String", "User"},
				Meta: &atypes.ParamMeta{
					Label: "Sender",
				},
			},
			{
				Name:  "to",
				Types: []string{"String", "KV", "User"},
				Meta: &atypes.ParamMeta{
					Label: "Recipients",
				},
			},
			{
				Name:  "cc",
				Types: []string{"String", "KV", "User"},
				Meta: &atypes.ParamMeta{
					Label: "CC",
				},
			},
			{
				Name:  "html",
				Types: []string{"String", "Reader"},
				Meta: &atypes.ParamMeta{
					Label: "HTML message body",
				},
			},
			{
				Name:  "plain",
				Types: []string{"String", "Reader"},
				Meta: &atypes.ParamMeta{
					Label: "Plain text message body",
				},
			},
		},

		Results: []*atypes.Param{

			{
				Name:  "message",
				Types: []string{"EmailMessage"},
			},
		},

		Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
			var (
				args = &emailMessageArgs{
					hasSubject: in.Has("subject"),
					hasReplyTo: in.Has("replyTo"),
					hasFrom:    in.Has("from"),
					hasTo:      in.Has("to"),
					hasCc:      in.Has("cc"),
					hasHtml:    in.Has("html"),
					hasPlain:   in.Has("plain"),
				}
			)

			if err = in.Decode(args); err != nil {
				return
			}

			// Converting Subject argument
			if args.hasSubject {
				aux := expr.Must(expr.Select(in, "subject"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.subjectString = aux.Get().(string)
				case h.reg.Type("Reader").Type():
					args.subjectStream = aux.Get().(io.Reader)
				}
			}

			// Converting ReplyTo argument
			if args.hasReplyTo {
				aux := expr.Must(expr.Select(in, "replyTo"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.replyToString = aux.Get().(string)
				case h.reg.Type("User").Type():
					args.replyToUser = aux.Get().(*sysTypes.User)
				}
			}

			// Converting From argument
			if args.hasFrom {
				aux := expr.Must(expr.Select(in, "from"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.fromString = aux.Get().(string)
				case h.reg.Type("User").Type():
					args.fromUser = aux.Get().(*sysTypes.User)
				}
			}

			// Converting To argument
			if args.hasTo {
				aux := expr.Must(expr.Select(in, "to"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.toString = aux.Get().(string)
				case h.reg.Type("KV").Type():
					args.toKV = aux.Get().(map[string]string)
				case h.reg.Type("User").Type():
					args.toUser = aux.Get().(*sysTypes.User)
				}
			}

			// Converting Cc argument
			if args.hasCc {
				aux := expr.Must(expr.Select(in, "cc"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.ccString = aux.Get().(string)
				case h.reg.Type("KV").Type():
					args.ccKV = aux.Get().(map[string]string)
				case h.reg.Type("User").Type():
					args.ccUser = aux.Get().(*sysTypes.User)
				}
			}

			// Converting Html argument
			if args.hasHtml {
				aux := expr.Must(expr.Select(in, "html"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.htmlString = aux.Get().(string)
				case h.reg.Type("Reader").Type():
					args.htmlStream = aux.Get().(io.Reader)
				}
			}

			// Converting Plain argument
			if args.hasPlain {
				aux := expr.Must(expr.Select(in, "plain"))
				switch aux.Type() {
				case h.reg.Type("String").Type():
					args.plainString = aux.Get().(string)
				case h.reg.Type("Reader").Type():
					args.plainStream = aux.Get().(io.Reader)
				}
			}

			var results *emailMessageResults
			if results, err = h.message(ctx, args); err != nil {
				return
			}

			out = &expr.Vars{}

			{
				// converting results.Message (*emailMessage) to EmailMessage
				var (
					tval expr.TypedValue
				)

				if tval, err = h.reg.Type("EmailMessage").Cast(results.Message); err != nil {
					return
				} else if err = expr.Assign(out, "message", tval); err != nil {
					return
				}
			}

			return
		},
	}
}