-
Notifications
You must be signed in to change notification settings - Fork 15
/
main.go
154 lines (132 loc) · 4.31 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
package main
import (
"os"
"strconv"
"strings"
"flag"
"bytes"
"log"
"net"
"gopkg.in/telegram-bot-api.v4"
"github.com/spf13/viper"
"github.com/veqryn/go-email/email"
"github.com/ircop/smtp2tg/smtpd"
)
var receivers map[string]string
var bot *tgbotapi.BotAPI
var debug bool
func main() {
configFilePath := flag.String("c", "./smtp2tg.toml", "Config file location")
//pidFilePath := flag.String("p", "/var/run/smtp2tg.pid", "Pid file location")
flag.Parse()
// Load & parse config
viper.SetConfigFile(*configFilePath)
err := viper.ReadInConfig()
if( err != nil ) {
log.Fatal(err.Error())
}
// Logging
logfile := viper.GetString("logging.file")
if( logfile == "" ) {
log.Println("No logging.file defined in config, outputting to stdout")
} else {
lf, err := os.OpenFile(logfile, os.O_APPEND | os.O_CREATE | os.O_RDWR, 0666)
if( err != nil ) {
log.Fatal(err.Error())
}
log.SetOutput(lf)
}
// Debug?
debug = viper.GetBool("logging.debug")
receivers = viper.GetStringMapString("receivers")
if( receivers["*"] == "" ) {
log.Fatal("No wildcard receiver (*) found in config.")
}
var token string = viper.GetString("bot.token")
if( token == "" ) {
log.Fatal("No bot.token defined in config")
}
var listen string = viper.GetString("smtp.listen")
var name string = viper.GetString("smtp.name")
if( listen == "" ) {
log.Fatal("No smtp.listen defined in config.")
}
if( name == "" ) {
log.Fatal("No smtp.name defined in config.")
}
// Initialize TG bot
bot, err = tgbotapi.NewBotAPI( token )
if( err != nil ) {
log.Fatal(err.Error())
}
log.Printf("Bot authorized as %s", bot.Self.UserName )
log.Printf("Initializing smtp server on %s...", listen)
// Initialize SMTP server
err_ := smtpd.ListenAndServe(listen, mailHandler, "mail2tg", "", debug)
if( err_ != nil ) {
log.Fatal(err_.Error())
}
}
func mailHandler(origin net.Addr, from string, to []string, data []byte) {
from = strings.Trim(from, " ")
to[0] = strings.Trim(to[0], " ")
to[0] = strings.Trim(to[0], "<")
to[0] = strings.Trim(to[0], ">")
msg, err := email.ParseMessage(bytes.NewReader(data))
if( err != nil ) {
log.Printf("[MAIL ERROR]: %s", err.Error())
return
}
subject := msg.Header.Get("Subject")
log.Printf("Received mail from '%s' for '%s' with subject '%s'", from, to[0], subject)
// Find receivers and send to TG
var tgid string
if( receivers[to[0]] != "" ) {
tgid = receivers[to[0]]
} else {
tgid = receivers["*"]
}
textMsgs := msg.MessagesContentTypePrefix("text")
images := msg.MessagesContentTypePrefix("image")
if len(textMsgs) == 0 && len(images) == 0 {
log.Printf("mail doesn't contain text or image")
return
}
log.Printf("Relaying message to: %v", tgid)
i, err := strconv.ParseInt(tgid, 10, 64)
if( err != nil ) {
log.Printf("[ERROR]: wrong telegram id: not int64")
return
}
if len(textMsgs) > 0 {
bodyStr := string(textMsgs[0].Body)
tgMsg := tgbotapi.NewMessage(i, bodyStr)
tgMsg.ParseMode = tgbotapi.ModeMarkdown
_, err = bot.Send(tgMsg)
if err != nil {
log.Printf("[ERROR]: telegram message send: '%s'", err.Error())
return
}
}
// TODO Better to use 'sendMediaGroup' to send all attachments as a
// single message, but go telegram api has not implemented it yet
// https://github.com/go-telegram-bot-api/telegram-bot-api/issues/143
for _, part := range msg.MessagesContentTypePrefix("image") {
_, params, err := part.Header.ContentDisposition()
if err != nil {
log.Printf("[ERROR]: content disposition parse: '%s'", err.Error())
return
}
text := params["filename"]
tgFile := tgbotapi.FileBytes{Name: text, Bytes: part.Body}
tgMsg := tgbotapi.NewPhotoUpload(i, tgFile)
tgMsg.Caption = text
// It's not a separate message, so disable notification
tgMsg.DisableNotification = true
_, err = bot.Send(tgMsg)
if err != nil {
log.Printf("[ERROR]: telegram photo send: '%s'", err.Error())
return
}
}
}