-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
190 lines (151 loc) · 5.8 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
)
var (
// Long-form flags
smtpServer string
smtpPort int
username string
password string
tlsMode string
configFile string
fromEmail string
toEmail string
subject string
body string
attachmentsFiles string
bodyFile string
// Short-form flags
smtpServerShort string
smtpPortShort int
usernameShort string
passwordShort string
tlsModeShort string
configFileShort string
fromEmailShort string
toEmailShort string
subjectShort string
bodyShort string
attachmentsFilesShort string
bodyFileShort string
)
func init() {
// Long-form flags
flag.StringVar(&smtpServer, "smtp-server", "", "SMTP server for sending emails")
flag.IntVar(&smtpPort, "smtp-port", 587, "SMTP server port")
flag.StringVar(&username, "smtp-username", "", "Username for SMTP authentication")
flag.StringVar(&password, "smtp-password", "", "Password for SMTP authentication")
flag.StringVar(&tlsMode, "tls-mode", "tls", "TLS mode (none, tls-skip, tls)")
flag.StringVar(&configFile, "config", "", "Path to the SMTP config file")
flag.StringVar(&fromEmail, "from-email", "", "Email address to send from")
flag.StringVar(&toEmail, "to-email", "", "Email addresses that will receive the email, comma-separated")
flag.StringVar(&subject, "subject", "", "Subject of the email")
flag.StringVar(&body, "body", "", "Body of the email")
flag.StringVar(&attachmentsFiles, "attachments", "", "File paths for attachments, comma-separated")
flag.StringVar(&bodyFile, "body-file", "", "File path for email body")
// Short-form flags
flag.StringVar(&smtpServerShort, "s", "", "SMTP server for sending emails (short)")
flag.IntVar(&smtpPortShort, "p", 587, "SMTP server port (short)")
flag.StringVar(&usernameShort, "u", "", "Username for SMTP authentication (short)")
flag.StringVar(&passwordShort, "w", "", "Password for SMTP authentication (short)")
flag.StringVar(&tlsModeShort, "l", "tls", "TLS mode (short)")
flag.StringVar(&configFileShort, "c", "", "Path to the SMTP config file (short)")
flag.StringVar(&fromEmailShort, "f", "", "Email address to send from (short)")
flag.StringVar(&toEmailShort, "t", "", "Email addresses that will receive the email, comma-separated (short)")
flag.StringVar(&subjectShort, "h", "", "Subject of the email (short)")
flag.StringVar(&bodyShort, "b", "", "Body of the email (short)")
flag.StringVar(&attachmentsFilesShort, "af", "", "File paths for attachments, comma-separated (short)")
flag.StringVar(&bodyFileShort, "bf", "", "File path for email body (short)")
}
func main() {
// Override the default flag.Usage
flag.Usage = Usage
flag.Parse()
var config Config = Config{}
// Load config file
configFile = priorityString([]string{configFile, configFileShort})
if configFile == "" {
// config file not provided -- look for default file
if path, err := os.UserConfigDir(); err == nil {
path = filepath.Join(path, "mail2go", "config.json")
if _, err := os.Stat(path); err == nil {
configFile = path
}
}
}
if configFile != "" {
c, err := loadConfig(configFile)
if err != nil {
fmt.Printf("Error loading config file: %v", err)
}
config = c
}
// Clearly define our config priorities, lowest to highest: config files, long flags, short flags
smtpServer = priorityString([]string{config.SMTPServer, smtpServer, smtpServerShort})
smtpPort = priorityInt(587, []int{config.SMTPPort, smtpPort, smtpPortShort})
username = priorityString([]string{config.SMTPUsername, username, usernameShort})
password = priorityString([]string{config.SMTPPassword, password, passwordShort})
tlsMode = priorityString([]string{config.TLSMode, tlsMode, tlsModeShort})
fromEmail = priorityString([]string{config.FromEmail, fromEmail, fromEmailShort})
toEmail = priorityString([]string{toEmail, toEmailShort})
subject = priorityString([]string{subject, subjectShort})
body = priorityString([]string{body, bodyShort})
attachmentsFiles = priorityString([]string{attachmentsFiles, attachmentsFilesShort})
bodyFile = priorityString([]string{bodyFile, bodyFileShort})
// Check if required flags or config values are missing
if smtpServer == "" || fromEmail == "" || toEmail == "" || subject == "" {
fmt.Fprintln(os.Stderr, "Error: Required flags or config values are missing.")
Usage()
}
// Check if either direct input or file path is provided for body
if body == "" && bodyFile == "" {
fmt.Fprintln(os.Stderr, "Error: Subject and body are required, either directly or through a specified file.")
Usage()
}
// Read body from files if provided
if bodyFile != "" {
content, err := os.ReadFile(bodyFile)
if err != nil {
fmt.Printf("\nError reading body file: %v\n", err)
}
body = priorityString([]string{string(content), body}) //preserve the "flags override files" semantic
}
// Split attachment file paths
var attachmentPaths []string
if attachmentsFiles != "" {
attachmentPaths = strings.Split(attachmentsFiles, ",")
}
// Split recipient email addresses
var toEmails []string
if toEmail != "" {
toEmails = strings.Split(toEmail, ",")
}
if len(toEmails) == 0 {
fmt.Fprintln(os.Stderr, "Error: At least one recipient email address is required.")
Usage()
}
sendEmail(smtpServer, smtpPort, username, password, fromEmail, toEmails, subject, body, bodyFile, attachmentPaths, tlsMode)
}
func priorityString(strings []string) string {
var result = ""
for _, val := range strings {
if val != "" {
result = val
}
}
return result
}
func priorityInt(emptyval int, ints []int) int {
var result = emptyval
for _, val := range ints {
if val != emptyval {
result = val
}
}
return result
}