From 262c59f766eb14c6a4795263745bcc86a9afdb0d Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Mon, 2 Dec 2019 14:25:47 +0100 Subject: [PATCH 1/9] added DefaultProfile settings --- conf/mail2most.conf | 69 +++++++++++++++++++++++++++++++++++++-------- lib/config.go | 7 +++-- lib/internals.go | 14 +++++++++ 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/conf/mail2most.conf b/conf/mail2most.conf index 8cf79ab..54e6833 100644 --- a/conf/mail2most.conf +++ b/conf/mail2most.conf @@ -16,10 +16,59 @@ # Logfile is used if Output is set to "logfile" Logfile = "mail2most.log" +# The DefaultProfile defines a set of defaults used in Profiles that do not define the specific section +# if you create an empty Profile the DefaultProfile is used +# if a Profile contains the section Mail, Mattermost or Filter this section will overwrite the sections from the Default Profile +# at least an empty Profile has to be created for the DefaultProfile to be processed +# only defining the DefaultProfile without having a [Profile] defined will not work +[DefaultProfile] + # The DefaultProfile.Mail defines a default mailserver + # if your Profile hast no defined mailserver this information will be used + [DefaultProfile.Mail] + ImapServer = "default.mail.example.com:993" + Username = "username" + Password = "password" + # ReadOnly does not change any flags on emails + ReadOnly = true + # ImapTLS allows you to enable / disable tls encryption whithin the imap protocol + ImapTLS = true + + # The DefaultProfile.Mattermost defines a default mattermost server + # if your Profile has no defined mattermost server this information will be used + [DefaultProfile.Mattermost] + URL = "https://default.mattermost.example.com" + Team = "defaultTeam" + Username = "username" + Password = "password" + # Channels contains all channels to post your messages + Channels = ["#default-channel"] + # SubjectOnly will post only the mail subject + SubjectOnly = false + # StripHTML will remove all HTML tags bevor sending a msg to mattermost + StripHTML = true + # HideFrom allows you to hide the From Address in mattermost messages + HideFrom= false + + # The DefaultProfile.Filter defines a default filter + # if your Profile has no defined filter this information will be used + [DefaultProfile.Filter] + # Folders filters your mails only in specific email folders + Folders = ["some-default-email-folder", "some-other-default-email-folder"] + # Unseen lets you process unseen mails only + Unseen = false + # From filters for defined from addresses + From = ["test@example.com"] + # To filters for defined to addresses + To = ["info@example.com"] + # Subject filters if the email subject contains one of the defined strings + Subject = ["example subject"] + # TimeRange will only process mails that are not older than the defined time range + TimeRange = "24h" + #[[Profile]] defines a profile, you can have as many as you want [[Profile]] - #[Profile.Mail] contains the mail server configuration + #[Profile.Mail] contains the mail server configuration and overwrites the default [Profile.Mail] ImapServer = "mail.example.com:993" Username = "username" @@ -29,7 +78,7 @@ # ImapTLS allows you to enable / disable tls encryption whithin the imap protocol ImapTLS = true - #[Profile.Mattermost] contains the mattermost configuration + #[Profile.Mattermost] contains the mattermost configuration and overwrites the default [Profile.Mattermost] URL = "https://mattermost.example.com" Team = "exampleTeam" @@ -44,7 +93,7 @@ # HideFrom allows you to hide the From Address in mattermost messages HideFrom= false - #[Profile.Filter] contains all filters that are applied to your mails + #[Profile.Filter] contains all filters that are applied to your mails and overwrites the default [Profile.Filter] # Folders filters your mails only in specific email folders Folders = ["some-email-folder", "some-other-email-folder"] @@ -83,12 +132,8 @@ Broadcast = [] SubjectOnly = false - # you are free to create another set of filters for your new profile - [Profile.Filter] - Folders = ["some-email-folder", "some-other-email-folder"] - Unseen = false - # or filter multiple from to or subjects - From = ["test@example.com", "test@example.com"] - To = ["info@example.com", "test@example.com"] - Subject = ["example subject", "another subject"] - TimeRange = "24h" + # if you dont add for example [Profile.Filter] the filters defined in the [DefaultProfile.Filter] section are used + + +# if you create an empty Profile the defaults were used +[[Profile]] diff --git a/lib/config.go b/lib/config.go index 7347b64..3b5761b 100644 --- a/lib/config.go +++ b/lib/config.go @@ -7,9 +7,10 @@ import ( ) type config struct { - General general - Logging logging - Profiles []profile `toml:"Profile"` + General general + Logging logging + Profiles []profile `toml:"Profile"` + DefaultProfile profile } type general struct { File string diff --git a/lib/internals.go b/lib/internals.go index 206ff48..64e8e21 100644 --- a/lib/internals.go +++ b/lib/internals.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/ioutil" + "reflect" "strings" "time" @@ -27,6 +28,19 @@ func New(confPath string) (Mail2Most, error) { if err != nil { return Mail2Most{}, err } + + for k, p := range conf.Profiles { + if p.Mail == (maildata{}) { + conf.Profiles[k].Mail = conf.DefaultProfile.Mail + } + if reflect.DeepEqual(p.Mattermost, mattermost{}) { + conf.Profiles[k].Mattermost = conf.DefaultProfile.Mattermost + } + if reflect.DeepEqual(p.Filter, filter{}) { + conf.Profiles[k].Filter = conf.DefaultProfile.Filter + } + } + m := Mail2Most{Config: conf} err = m.initLogger() if err != nil { From 13279e5bc708fd7722e3dbef061253356df496c8 Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Mon, 2 Dec 2019 15:25:14 +0100 Subject: [PATCH 2/9] added users --- conf/mail2most.conf | 10 ++- lib/config.go | 1 + lib/mail2most.go | 3 +- lib/mattermost.go | 150 ++++++++++++++++++++++++++++++-------------- 4 files changed, 115 insertions(+), 49 deletions(-) diff --git a/conf/mail2most.conf b/conf/mail2most.conf index 54e6833..6b53dfd 100644 --- a/conf/mail2most.conf +++ b/conf/mail2most.conf @@ -40,8 +40,12 @@ Team = "defaultTeam" Username = "username" Password = "password" - # Channels contains all channels to post your messages + # Channels contains all channels to post your messages + # if no channel is defined nothing is posted into a channel Channels = ["#default-channel"] + # Users contains all users to post your message to, you can use the username or email address + # if no users are defined nothing is posted to any user + Users = ["bob","alice@example.com"] # SubjectOnly will post only the mail subject SubjectOnly = false # StripHTML will remove all HTML tags bevor sending a msg to mattermost @@ -86,6 +90,8 @@ Password = "password" # Channels contains all channels to post your messages Channels = ["#some-channel"] + # Users contains all users to post your message to, you can use the username or email address + Users = ["bob","alice@example.com"] # SubjectOnly will post only the mail subject SubjectOnly = false # StripHTML will remove all HTML tags bevor sending a msg to mattermost @@ -127,6 +133,8 @@ Password = "password" # you can even post to multiple channels if you want to Channels = ["#some-other-channel","#some-crazy-channel"] + # Users contains all users to post your message to, you can use the username or email address + Users = ["bob","alice@example.com"] # Broadcast allows you to set @channel, @all, @here etc at the begining fo the message # Broadcast = ["@channel", "@all"] Broadcast = [] diff --git a/lib/config.go b/lib/config.go index 3b5761b..0ffe229 100644 --- a/lib/config.go +++ b/lib/config.go @@ -45,6 +45,7 @@ type filter struct { type mattermost struct { URL, Team, Username, Password string Channels []string + Users []string Broadcast []string SubjectOnly bool StripHTML bool diff --git a/lib/mail2most.go b/lib/mail2most.go index 53ac683..355aff1 100644 --- a/lib/mail2most.go +++ b/lib/mail2most.go @@ -74,8 +74,9 @@ func (m Mail2Most) Run() error { m.Error("Mattermost Error", map[string]interface{}{ "Error": err, }) + } else { + alreadySend[p] = append(alreadySend[p], mail.ID) } - alreadySend[p] = append(alreadySend[p], mail.ID) err = writeToFile(alreadySend, m.Config.General.File) if err != nil { diff --git a/lib/mattermost.go b/lib/mattermost.go index 87e139f..6e296c5 100644 --- a/lib/mattermost.go +++ b/lib/mattermost.go @@ -28,6 +28,63 @@ func (m Mail2Most) PostMattermost(profile int, mail Mail) error { } defer c.Logout() + // check if body is base64 encoded + var body string + bb, err := base64.StdEncoding.DecodeString(mail.Body) + if err != nil { + body = mail.Body + } else { + body = string(bb) + } + + if m.Config.Profiles[profile].Mattermost.StripHTML { + body = html2text.HTML2Text(body) + mail.Subject = html2text.HTML2Text(mail.Subject) + mail.From[0].PersonalName = html2text.HTML2Text(mail.From[0].PersonalName) + mail.From[0].MailboxName = html2text.HTML2Text(mail.From[0].MailboxName) + mail.From[0].HostName = html2text.HTML2Text(mail.From[0].HostName) + } + + msg := ":email: " + + if !m.Config.Profiles[profile].Mattermost.HideFrom { + msg += fmt.Sprintf("_From: **<%s> %s@%s**_", + mail.From[0].PersonalName, + mail.From[0].MailboxName, + mail.From[0].HostName, + ) + } + + if m.Config.Profiles[profile].Mattermost.SubjectOnly { + msg += fmt.Sprintf( + "\n>_%s_\n\n", + mail.Subject, + ) + } else { + msg += fmt.Sprintf( + "\n>_%s_\n\n```\n%s```\n", + mail.Subject, + body, + ) + } + + for _, b := range m.Config.Profiles[profile].Mattermost.Broadcast { + msg = b + " " + msg + } + // max message length is about 16383 + // https://docs.mattermost.com/administration/important-upgrade-notes.html + if len(msg) > 16383 { + msg = msg[0:16382] + } + + fallback := fmt.Sprintf( + ":email: _From: **<%s> %s@%s**_\n>_%s_\n\n", + mail.From[0].PersonalName, + mail.From[0].MailboxName, + mail.From[0].HostName, + mail.Subject, + ) + for _, channel := range m.Config.Profiles[profile].Mattermost.Channels { channelName := strings.ReplaceAll(channel, "#", "") @@ -38,67 +95,66 @@ func (m Mail2Most) PostMattermost(profile int, mail Mail) error { return resp.Error } - // check if body is base64 encoded - var body string - bb, err := base64.StdEncoding.DecodeString(mail.Body) - if err != nil { - body = mail.Body - } else { - body = string(bb) + post := &model.Post{ChannelId: ch.Id, Message: msg} + _, resp = c.CreatePost(post) + if resp.Error != nil { + m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback send only subject"}) + post := &model.Post{ChannelId: ch.Id, Message: fallback} + _, resp = c.CreatePost(post) + if resp.Error != nil { + m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback not working"}) + return resp.Error + } } + } - if m.Config.Profiles[profile].Mattermost.StripHTML { - body = html2text.HTML2Text(body) - mail.Subject = html2text.HTML2Text(mail.Subject) - mail.From[0].PersonalName = html2text.HTML2Text(mail.From[0].PersonalName) - mail.From[0].MailboxName = html2text.HTML2Text(mail.From[0].MailboxName) - mail.From[0].HostName = html2text.HTML2Text(mail.From[0].HostName) + var ( + me *model.User + resp *model.Response + ) + // who am i + // user is defined by its email address + if strings.Contains(m.Config.Profiles[profile].Mattermost.Username, "@") { + me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") + if resp.Error != nil { + return resp.Error } - - msg := ":email: " - - if !m.Config.Profiles[profile].Mattermost.HideFrom { - msg += fmt.Sprintf("_From: **<%s> %s@%s**_", - mail.From[0].PersonalName, - mail.From[0].MailboxName, - mail.From[0].HostName, - ) + } else { + me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") + if resp.Error != nil { + return resp.Error } + } + myid := me.Id - if m.Config.Profiles[profile].Mattermost.SubjectOnly { - msg += fmt.Sprintf( - "\n>_%s_\n\n", - mail.Subject, - ) + for _, user := range m.Config.Profiles[profile].Mattermost.Users { + + var ( + u *model.User + ) + // user is defined by its email address + if strings.Contains(user, "@") { + u, resp = c.GetUserByEmail(user, "") + if resp.Error != nil { + return resp.Error + } } else { - msg += fmt.Sprintf( - "\n>_%s_\n\n```\n%s```\n", - mail.Subject, - body, - ) + u, resp = c.GetUserByUsername(user, "") + if resp.Error != nil { + return resp.Error + } } - for _, b := range m.Config.Profiles[profile].Mattermost.Broadcast { - msg = b + " " + msg - } - // max message length is about 16383 - // https://docs.mattermost.com/administration/important-upgrade-notes.html - if len(msg) > 16383 { - msg = msg[0:16382] + ch, resp := c.CreateDirectChannel(myid, u.Id) + if resp.Error != nil { + return resp.Error } post := &model.Post{ChannelId: ch.Id, Message: msg} _, resp = c.CreatePost(post) if resp.Error != nil { m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback send only subject"}) - msg = fmt.Sprintf( - ":email: _From: **<%s> %s@%s**_\n>_%s_\n\n", - mail.From[0].PersonalName, - mail.From[0].MailboxName, - mail.From[0].HostName, - mail.Subject, - ) - post := &model.Post{ChannelId: ch.Id, Message: msg} + post := &model.Post{ChannelId: ch.Id, Message: fallback} _, resp = c.CreatePost(post) if resp.Error != nil { m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback not working"}) From 25fa779d25fce8ff9ba29ab819e14c49fc7a20ca Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 10:09:29 +0100 Subject: [PATCH 3/9] added IngoreDefaults option and data.json vs config inconsistency check --- conf/mail2most.conf | 4 ++++ lib/config.go | 7 ++++--- lib/internals.go | 18 ++++++++++-------- lib/mail2most.go | 14 ++++++++++++-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/conf/mail2most.conf b/conf/mail2most.conf index 6b53dfd..0d59179 100644 --- a/conf/mail2most.conf +++ b/conf/mail2most.conf @@ -71,6 +71,10 @@ #[[Profile]] defines a profile, you can have as many as you want [[Profile]] + # IgnoreDefaults lets you ignore the DefaultProfile settings and forces to set everything in the Profile + # this option should only be used if you try to overwrite a default with an empty value + # the better way is to define the value only in the profile and not in the defaults + IgnoreDefaults = false #[Profile.Mail] contains the mail server configuration and overwrites the default [Profile.Mail] diff --git a/lib/config.go b/lib/config.go index 0ffe229..dd6183a 100644 --- a/lib/config.go +++ b/lib/config.go @@ -25,9 +25,10 @@ type logging struct { } type profile struct { - Mail maildata - Mattermost mattermost - Filter filter + IgnoreDefaults bool + Mail maildata + Mattermost mattermost + Filter filter } type maildata struct { diff --git a/lib/internals.go b/lib/internals.go index 64e8e21..349c106 100644 --- a/lib/internals.go +++ b/lib/internals.go @@ -30,14 +30,16 @@ func New(confPath string) (Mail2Most, error) { } for k, p := range conf.Profiles { - if p.Mail == (maildata{}) { - conf.Profiles[k].Mail = conf.DefaultProfile.Mail - } - if reflect.DeepEqual(p.Mattermost, mattermost{}) { - conf.Profiles[k].Mattermost = conf.DefaultProfile.Mattermost - } - if reflect.DeepEqual(p.Filter, filter{}) { - conf.Profiles[k].Filter = conf.DefaultProfile.Filter + if !p.IgnoreDefaults { + if p.Mail == (maildata{}) { + conf.Profiles[k].Mail = conf.DefaultProfile.Mail + } + if reflect.DeepEqual(p.Mattermost, mattermost{}) { + conf.Profiles[k].Mattermost = conf.DefaultProfile.Mattermost + } + if reflect.DeepEqual(p.Filter, filter{}) { + conf.Profiles[k].Filter = conf.DefaultProfile.Filter + } } } diff --git a/lib/mail2most.go b/lib/mail2most.go index 355aff1..9fc349d 100644 --- a/lib/mail2most.go +++ b/lib/mail2most.go @@ -32,8 +32,19 @@ func (m Mail2Most) Run() error { // this is nessasary if new profiles are added // and the caching file does not contain any caching // for this profile + l := len(alreadySend) for k, v := range alreadySendFile { - alreadySend[k] = v + if k < l { + alreadySend[k] = v + } + if k >= l { + m.Error("data.json error", map[string]interface{}{ + "error": "data.json contains more profile information than defined in the config", + "cause": "this happens if profiles are deleted from the config file and can create inconsistencies", + "solution": "delete the data.json file", + "note": "by deleting the data.json file all mails are parsed and send again", + }) + } } // set a 10 seconds sleep default if no TimeInterval is defined @@ -92,5 +103,4 @@ func (m Mail2Most) Run() error { }) time.Sleep(time.Duration(m.Config.General.TimeInterval) * time.Second) } - } From 8947a1433ddb466e5b588d348c2f62e1466d3c79 Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 10:18:09 +0100 Subject: [PATCH 4/9] improved default config --- conf/mail2most.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conf/mail2most.conf b/conf/mail2most.conf index 0d59179..f97c535 100644 --- a/conf/mail2most.conf +++ b/conf/mail2most.conf @@ -120,6 +120,10 @@ # you can define multiple profiles by adding another [[Profile]] [[Profile]] + # IgnoreDefaults lets you ignore the DefaultProfile settings and forces to set everything in the Profile + # this option should only be used if you try to overwrite a default with an empty value + # the better way is to define the value only in the profile and not in the defaults + IgnoreDefaults = false # you can use the same mailserver as in the other profile or even another one [Profile.Mail] @@ -149,3 +153,4 @@ # if you create an empty Profile the defaults were used [[Profile]] + # setting IgnoreDefaults = true in an empty profile will result in an error since nothing is defined then From 4184e02bd8a9cdad09ea2ba5b9302feda933ed8b Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 11:03:38 +0100 Subject: [PATCH 5/9] added reflection for default values to only overwrite specific non zero values defined in every profile section --- lib/internals.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/internals.go b/lib/internals.go index 349c106..17b5245 100644 --- a/lib/internals.go +++ b/lib/internals.go @@ -31,15 +31,24 @@ func New(confPath string) (Mail2Most, error) { for k, p := range conf.Profiles { if !p.IgnoreDefaults { - if p.Mail == (maildata{}) { - conf.Profiles[k].Mail = conf.DefaultProfile.Mail - } - if reflect.DeepEqual(p.Mattermost, mattermost{}) { - conf.Profiles[k].Mattermost = conf.DefaultProfile.Mattermost - } - if reflect.DeepEqual(p.Filter, filter{}) { - conf.Profiles[k].Filter = conf.DefaultProfile.Filter + // create a default profile and overwrite what is defined in the profile + prof := conf.DefaultProfile + voft := reflect.ValueOf(&prof).Elem() + vof := reflect.ValueOf(p) + for i := 0; i < voft.NumField(); i++ { + for j := 0; j < vof.NumField(); j++ { + if vof.Field(j).Type().Kind() == reflect.Struct { + if voft.Type().Field(i).Name == vof.Type().Field(j).Name { + for k := 0; k < vof.Field(j).NumField(); k++ { + if !vof.Field(j).Field(k).IsZero() { + voft.Field(i).FieldByName(vof.Field(j).Type().Field(k).Name).Set(vof.Field(j).Field(k)) + } + } + } + } + } } + conf.Profiles[k] = prof } } From 841d2f5ee18e6d9b0afd461d4b619a2fd779b2fc Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 11:11:30 +0100 Subject: [PATCH 6/9] updated features in README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 05643b5..07b6051 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,10 @@ Filter emails from mail accounts and send them to mattermost. - Filter mails by To - Filter mails by Subject - Filter mails by TimeRange -- Mattermost Broadcasts +- Mattermost broadcasts - Choose to post Subject and Body or Subject only +- Send to channels and/or users +- Profile management including default profiles Missing feature or found a bug ? Feel free to open an [issue](https://github.com/cseeger-epages/mail2most/issues) and let us know ! From f07874515b1c12fc27b181b2f4aeddba8634be9c Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 13:13:14 +0100 Subject: [PATCH 7/9] added common problems --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 07b6051..8cc821c 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,14 @@ systemctl enable mail2most systemctl start mail2most ``` +## Common problems + +**Problem: mail2most crashes after profile changes** +Solution: This happens when the data.json is not consistent to the config changes. Delete data.json to solve this problem. + +**Problem: Channel contains special characters mattermost can not found the channel** +Solution: Mattermost does not support special characters for channel names, only in display names. To find the correct channel name use the last part of the url found under `view info` + # Contribution to Mail2Most Thank you for participating to this project. From 2f4b52708b7d292564af963b2cb5d5352aa62980 Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Tue, 3 Dec 2019 14:36:07 +0100 Subject: [PATCH 8/9] added AccessToken login --- conf/mail2most.conf | 9 +++++ lib/config.go | 14 +++---- lib/mattermost.go | 92 ++++++++++++++++++++++++++------------------- 3 files changed, 70 insertions(+), 45 deletions(-) diff --git a/conf/mail2most.conf b/conf/mail2most.conf index f97c535..824c03b 100644 --- a/conf/mail2most.conf +++ b/conf/mail2most.conf @@ -38,8 +38,11 @@ [DefaultProfile.Mattermost] URL = "https://default.mattermost.example.com" Team = "defaultTeam" + # you can define username password Username = "username" Password = "password" + # or accesstoken + AccessToken = "mytoken" # Channels contains all channels to post your messages # if no channel is defined nothing is posted into a channel Channels = ["#default-channel"] @@ -90,8 +93,11 @@ [Profile.Mattermost] URL = "https://mattermost.example.com" Team = "exampleTeam" + # you can define username password Username = "username" Password = "password" + # or accesstoken + AccessToken = "mytoken" # Channels contains all channels to post your messages Channels = ["#some-channel"] # Users contains all users to post your message to, you can use the username or email address @@ -137,8 +143,11 @@ [Profile.Mattermost] URL = "https://mattermost.example.com" Team = "anotherTeam" + # you can define username password Username = "username" Password = "password" + # or accesstoken + AccessToken = "mytoken" # you can even post to multiple channels if you want to Channels = ["#some-other-channel","#some-crazy-channel"] # Users contains all users to post your message to, you can use the username or email address diff --git a/lib/config.go b/lib/config.go index dd6183a..f6dab95 100644 --- a/lib/config.go +++ b/lib/config.go @@ -44,13 +44,13 @@ type filter struct { } type mattermost struct { - URL, Team, Username, Password string - Channels []string - Users []string - Broadcast []string - SubjectOnly bool - StripHTML bool - HideFrom bool + URL, Team, Username, Password, AccessToken string + Channels []string + Users []string + Broadcast []string + SubjectOnly bool + StripHTML bool + HideFrom bool } func parseConfig(fileName string, conf *config) error { diff --git a/lib/mattermost.go b/lib/mattermost.go index 6e296c5..d54140d 100644 --- a/lib/mattermost.go +++ b/lib/mattermost.go @@ -12,9 +12,22 @@ import ( func (m Mail2Most) mlogin(profile int) (*model.Client4, error) { c := model.NewAPIv4Client(m.Config.Profiles[profile].Mattermost.URL) - _, resp := c.Login(m.Config.Profiles[profile].Mattermost.Username, m.Config.Profiles[profile].Mattermost.Password) - if resp.Error != nil { - return nil, resp.Error + if m.Config.Profiles[profile].Mattermost.Username != "" && m.Config.Profiles[profile].Mattermost.Password != "" { + _, resp := c.Login(m.Config.Profiles[profile].Mattermost.Username, m.Config.Profiles[profile].Mattermost.Password) + if resp.Error != nil { + return nil, resp.Error + } + } else if m.Config.Profiles[profile].Mattermost.AccessToken != "" { + c.AuthToken = m.Config.Profiles[profile].Mattermost.AccessToken + c.AuthType = "BEARER" + r, err := c.DoApiGet("/users/me", "") + if err != nil { + return nil, err + } + u := model.UserFromJson(r.Body) + m.Config.Profiles[profile].Mattermost.Username = u.Email + } else { + return nil, fmt.Errorf("no username, password or token is set") } return c, nil @@ -108,57 +121,60 @@ func (m Mail2Most) PostMattermost(profile int, mail Mail) error { } } - var ( - me *model.User - resp *model.Response - ) - // who am i - // user is defined by its email address - if strings.Contains(m.Config.Profiles[profile].Mattermost.Username, "@") { - me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") - if resp.Error != nil { - return resp.Error - } - } else { - me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") - if resp.Error != nil { - return resp.Error - } - } - myid := me.Id - - for _, user := range m.Config.Profiles[profile].Mattermost.Users { + if len(m.Config.Profiles[profile].Mattermost.Users) > 0 { var ( - u *model.User + me *model.User + resp *model.Response ) + + // who am i // user is defined by its email address - if strings.Contains(user, "@") { - u, resp = c.GetUserByEmail(user, "") + if strings.Contains(m.Config.Profiles[profile].Mattermost.Username, "@") { + me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") if resp.Error != nil { return resp.Error } } else { - u, resp = c.GetUserByUsername(user, "") + me, resp = c.GetUserByEmail(m.Config.Profiles[profile].Mattermost.Username, "") if resp.Error != nil { return resp.Error } } + myid := me.Id + + for _, user := range m.Config.Profiles[profile].Mattermost.Users { + var ( + u *model.User + ) + // user is defined by its email address + if strings.Contains(user, "@") { + u, resp = c.GetUserByEmail(user, "") + if resp.Error != nil { + return resp.Error + } + } else { + u, resp = c.GetUserByUsername(user, "") + if resp.Error != nil { + return resp.Error + } + } - ch, resp := c.CreateDirectChannel(myid, u.Id) - if resp.Error != nil { - return resp.Error - } + ch, resp := c.CreateDirectChannel(myid, u.Id) + if resp.Error != nil { + return resp.Error + } - post := &model.Post{ChannelId: ch.Id, Message: msg} - _, resp = c.CreatePost(post) - if resp.Error != nil { - m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback send only subject"}) - post := &model.Post{ChannelId: ch.Id, Message: fallback} + post := &model.Post{ChannelId: ch.Id, Message: msg} _, resp = c.CreatePost(post) if resp.Error != nil { - m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback not working"}) - return resp.Error + m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback send only subject"}) + post := &model.Post{ChannelId: ch.Id, Message: fallback} + _, resp = c.CreatePost(post) + if resp.Error != nil { + m.Error("Mattermost Post Error", map[string]interface{}{"Error": err, "status": "fallback not working"}) + return resp.Error + } } } } From 9d4fae1e55cccee94161252a071f7e2f2cf6e61a Mon Sep 17 00:00:00 2001 From: Carsten Seeger Date: Wed, 4 Dec 2019 09:50:16 +0100 Subject: [PATCH 9/9] line breaks --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8cc821c..8d1beaa 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,11 @@ systemctl start mail2most ## Common problems **Problem: mail2most crashes after profile changes** + Solution: This happens when the data.json is not consistent to the config changes. Delete data.json to solve this problem. **Problem: Channel contains special characters mattermost can not found the channel** + Solution: Mattermost does not support special characters for channel names, only in display names. To find the correct channel name use the last part of the url found under `view info` # Contribution to Mail2Most