Compare commits

15 Commits

Author SHA1 Message Date
bel
fbc173a78f casing 2026-02-24 00:01:33 -07:00
bel
8e40f85166 accept inbox 2026-02-24 00:00:46 -07:00
bel
1b74eb0d16 oauth can refresh 2026-02-23 23:58:23 -07:00
bel
5a4ce70451 can oauth 2026-02-23 22:59:40 -07:00
Bel LaPointe
14036702ee from gogs 2023-11-09 08:01:21 -07:00
Bel LaPointe
13d2acdf16 Merge branch 'master' of https://gogs.inhome.blapointe.com/local-sandbox/contact 2023-10-16 18:45:46 -06:00
Bel LaPointe
cae30cc5d1 oops pop3 is ordered asc 2023-10-16 18:45:38 -06:00
bel
bb4b7b4da8 down to go 1.20 2023-10-16 09:20:17 -06:00
Bel LaPointe
deb6c2d196 oops 2023-10-16 09:00:04 -06:00
Bel LaPointe
5191add42b pop3 log printf 2023-10-16 08:57:27 -06:00
Bel LaPointe
e3d5a7e221 recv now has -json for pretty print 2023-10-16 08:50:59 -06:00
Bel LaPointe
7d372adb78 fix pop3 fetching, limit recv to N bytes 2023-10-16 08:47:16 -06:00
Bel LaPointe
6b04a324f3 recv uses pop3 if provided 2023-10-16 08:23:42 -06:00
Bel LaPointe
48cb9bf32b accept username/password 2023-10-16 08:18:44 -06:00
Bel LaPointe
2313cc3ac5 mv /cmd to /cmd/* 2023-10-16 08:16:43 -06:00
15 changed files with 315 additions and 86 deletions

View File

@@ -3,7 +3,7 @@ package contact
import (
"crypto/tls"
"fmt"
"gogs.inhome.blapointe.com/local/system/sysconf"
"gitea.inhome.blapointe.com/local/system/sysconf"
"log"
"net"
"net/smtp"

View File

@@ -3,7 +3,7 @@ package contact
import (
"fmt"
"io/ioutil"
"gogs.inhome.blapointe.com/local/encryptor"
"gitea.inhome.blapointe.com/local/encryptor"
"os"
"testing"
)

View File

@@ -1,18 +0,0 @@
module gogs.inhome.blapointe.com/local-sandbox/contact
go 1.20
replace gogs.inhome.blapointe.com/local-sandbox/contact/contact => ./contact
require (
gogs.inhome.blapointe.com/local-sandbox/contact/contact v0.0.0-00010101000000-000000000000
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34
)
require (
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e // indirect
github.com/emersion/go-imap v1.2.0 // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

View File

@@ -1 +0,0 @@
wcBMA1Z2i1z86bGuAQgAZ1hb8CH2dcUuKWfstpILJqaonxEsinE2KgrzqHjEtogawL8pqNCWXPYgFxPh2sj4z9zI4/7+jcAcd3wz/mXj/FdaBUpFyMaC1cV9OmD8jSTvamBpG5KI2HHxuHRv0Y19rgjcXUjtZSJcu1ZYj6yMn2+KdDTHScRBXsiapOHc5S9nKrXJ69cFF7jvQRIgnn8KNVWmcau5BXKYrXa9XnwqZtNTFYBaPgyOWb8TMnBK93T4NegMTRj/XeGQ4NAT/5sfHNRvC84mYxZQFojuUTnT3zVgdET7o6AKrtsbHstL8mzaPjM9nMPZfTotSCzsXBE07Dt1zLmPXeo4eT0VyOUtpdLgAeMsLYZM1RdSXeECzuBk4EThv3zgP+IDH09o4OzkfKlNi862TzMNh6rMpCvBGuA14x4vOzvLsDLZ4MDiagQM2eCA4LzgQeQO24U6HvCz7cdAy22h7BqG4pOs1Hfhj8oA

View File

@@ -1,48 +0,0 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"strings"
"time"
"gogs.inhome.blapointe.com/local-sandbox/contact/contact"
"gogs.inhome.blapointe.com/local/args"
)
func main() {
emailer := contact.NewEmailer()
as := args.NewArgSet()
as.Append(args.STRING, "imap", "imap server:port", "imap.gmail.com:993")
as.Append(args.INT, "n", "limit (<1 for inf)", 10)
if err := as.Parse(); err != nil {
panic(err)
}
emailer.IMAP = as.Get("imap").GetString()
emailer.Limit = as.Get("n").GetInt()
msgs, err := emailer.Read()
if err != nil {
panic(err)
}
for msg := range msgs {
b, _ := ioutil.ReadAll(io.LimitReader(msg.Body, 1024))
s := strings.ReplaceAll(string(b), "\r\n", " ")
s = strings.ReplaceAll(string(s), "\n", " ")
s = strings.ReplaceAll(string(s), "\r", " ")
if !strings.Contains(s, " ") {
s = "..."
}
d, _ := msg.Header.Date()
d = d.In(time.Local)
fmt.Printf(
"@%+v @%+v: %+v: %s\n",
d.Format("06-01-02T15:04Z07"),
msg.Header.Get("From"),
msg.Header.Get("Subject"),
s,
)
}
}

21
cmd/recv/go.mod Normal file
View File

@@ -0,0 +1,21 @@
module gitea.inhome.blapointe.com/contact/cmd/recv
go 1.24.0
replace gitea.inhome.blapointe.com/local-sandbox/contact => ../../
require (
gitea.inhome.blapointe.com/local-sandbox/contact v0.0.0-00010101000000-000000000000
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56
)
require (
cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e // indirect
github.com/emersion/go-imap v1.2.0 // indirect
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
github.com/google/uuid v1.6.0 // indirect
golang.org/x/oauth2 v0.35.0 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

3
cmd/recv/go.sh Executable file
View File

@@ -0,0 +1,3 @@
#! /bin/sh
GOPRIVATE= GONOSUMDB=\* GONOPROXY=\* GOPROXY= go "$@"

26
cmd/recv/go.sum Normal file
View File

@@ -0,0 +1,26 @@
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56 h1:zTGGZ77KLFagqUvDSgTOnm0qF+iSLwQWiEtGjb2jjlY=
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56/go.mod h1:SqCOE3bE3wvrztVIQGHuyxHKfDjRKU9EWhBdkmkiwyc=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e h1:mQTN05gz0rDZSABqKMzAPMb5ATWcvvdMljRzEh0LjBo=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e/go.mod h1:alXX+s7a4cKaIprgjeEboqi4Tm7XR/HXEwUTxUV/ywU=
github.com/emersion/go-imap v1.2.0 h1:lyUQ3+EVM21/qbWE/4Ya5UG9r5+usDxlg4yfp3TgHFA=
github.com/emersion/go-imap v1.2.0/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

85
cmd/recv/main.go Executable file
View File

@@ -0,0 +1,85 @@
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/mail"
"os"
"strings"
"time"
"gitea.inhome.blapointe.com/local-sandbox/contact"
"gitea.inhome.blapointe.com/local/args"
)
func main() {
emailer := contact.NewEmailer()
as := args.NewArgSet()
as.Append(args.STRING, "imap", "imap server:port", "imap.gmail.com:993")
as.Append(args.STRING, "pop3", "pop3 server:port", "")
as.Append(args.INT, "n", "limit (<1 for inf)", 10)
as.Append(args.STRING, "u", "username", emailer.From)
as.Append(args.STRING, "p", "password", emailer.Password)
as.Append(args.INT, "b", "dont read more than this many characters", 4096)
as.Append(args.BOOL, "json", "output as json", false)
as.Append(args.STRING, "oauth", "", emailer.OAuth)
as.Append(args.STRING, "inbox", "", emailer.Inbox)
if err := as.Parse(); err != nil {
panic(err)
}
emailer.IMAP = as.Get("imap").GetString()
emailer.POP3 = as.Get("pop3").GetString()
emailer.Limit = as.Get("n").GetInt()
emailer.From = as.GetString("u")
emailer.Password = as.GetString("p")
emailer.OAuth = as.GetString("oauth")
emailer.Inbox = as.GetString("inbox")
var msgs <-chan *mail.Message
var err error
if emailer.POP3 != "" {
msgs, err = emailer.ReadPOP3()
} else {
msgs, err = emailer.Read()
}
if err != nil {
panic(err)
}
emails := make([]map[string]any, 0, emailer.Limit)
for msg := range msgs {
b, _ := ioutil.ReadAll(io.LimitReader(msg.Body, int64(as.GetInt("b"))))
s := strings.ReplaceAll(string(b), "\r\n", "\n")
s = strings.ReplaceAll(string(s), "\n", "\n")
s = strings.ReplaceAll(string(s), "\r", "\n")
if !strings.Contains(s, " ") {
s = "..."
}
d, _ := msg.Header.Date()
d = d.In(time.Local)
if as.GetBool("json") {
emails = append(emails, map[string]any{
"t": d.Format("06-01-02T15:04Z07"),
"from": msg.Header.Get("From"),
"subject": msg.Header.Get("Subject"),
"body": s,
})
} else {
fmt.Printf(
"@%+v @%+v: \n\t%+v: \n\t%s\n",
d.Format("06-01-02T15:04Z07"),
msg.Header.Get("From"),
msg.Header.Get("Subject"),
s,
)
}
}
if as.GetBool("json") {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(emails)
}
}

18
cmd/send/go.mod Normal file
View File

@@ -0,0 +1,18 @@
module gitea.inhome.blapointe.com/contact/cmd/send
go 1.21.0
replace gitea.inhome.blapointe.com/local-sandbox/contact => ../../
require (
gitea.inhome.blapointe.com/local-sandbox/contact v0.0.1
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56
)
require (
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e // indirect
github.com/emersion/go-imap v1.2.0 // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

View File

@@ -1,3 +1,5 @@
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56 h1:zTGGZ77KLFagqUvDSgTOnm0qF+iSLwQWiEtGjb2jjlY=
gitea.inhome.blapointe.com/local/args v0.0.0-20231109145953-eb2e1c1b8d56/go.mod h1:SqCOE3bE3wvrztVIQGHuyxHKfDjRKU9EWhBdkmkiwyc=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e h1:mQTN05gz0rDZSABqKMzAPMb5ATWcvvdMljRzEh0LjBo=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e/go.mod h1:alXX+s7a4cKaIprgjeEboqi4Tm7XR/HXEwUTxUV/ywU=
github.com/emersion/go-imap v1.2.0 h1:lyUQ3+EVM21/qbWE/4Ya5UG9r5+usDxlg4yfp3TgHFA=
@@ -6,8 +8,6 @@ github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwd
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34 h1:0tuX5dfOksiOQD1vbJjVNVTVxTTIng7UrUdSLF5T+Ao=
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34/go.mod h1:YG9n3Clg7683ohkVnJK2hdX8bBS9EojIsd1qPZumX0Y=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=

View File

@@ -1,8 +1,8 @@
package main
import (
"gogs.inhome.blapointe.com/local-sandbox/contact/contact"
"gogs.inhome.blapointe.com/local/args"
"gitea.inhome.blapointe.com/local-sandbox/contact"
"gitea.inhome.blapointe.com/local/args"
)
func main() {

156
email.go
View File

@@ -1,17 +1,30 @@
package contact
import (
"bytes"
"context"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/mail"
"net/smtp"
"net/url"
"os"
"strings"
"time"
"github.com/bytbox/go-pop3"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-sasl"
"github.com/google/uuid"
"golang.org/x/oauth2/authhandler"
"golang.org/x/oauth2/google"
)
type Emailer struct {
@@ -21,6 +34,8 @@ type Emailer struct {
IMAP string
Password string
Limit int
OAuth string
Inbox string
}
func NewEmailer() *Emailer {
@@ -34,6 +49,8 @@ func NewEmailer() *Emailer {
From: envOr("FROM", "breellocaldev@gmail.com"),
SMTP: envOr("SMTP", "smtp.gmail.com:465"),
Password: envOr("PASSWORD", "lhnjijrvqaesiufp"),
OAuth: envOr("OAUTH", ""),
Inbox: envOr("INBOX", "INBOX"),
}
}
@@ -42,14 +59,116 @@ func (e *Emailer) Read() (chan *mail.Message, error) {
}
func (e *Emailer) ReadIMAP() (chan *mail.Message, error) {
if e.OAuth != "" {
return e.oauthThenReadIMAP()
}
return e.readIMAP(e.From, e.Password)
}
func (e *Emailer) oauthThenReadIMAP() (chan *mail.Message, error) {
configJSON, err := e.configJSON()
if err != nil {
return nil, err
}
if token, _ := os.ReadFile(e.OAuth + ".token"); len(token) == 0 {
state := uuid.NewString()
verifier := uuid.NewString()
s256 := sha256.Sum256([]byte(verifier))
challenge := base64.RawURLEncoding.EncodeToString(s256[:])
pkceParams := authhandler.PKCEParams{Challenge: challenge, ChallengeMethod: "S256", Verifier: verifier}
config, err := google.ConfigFromJSON([]byte(configJSON), "https://mail.google.com/")
if err != nil {
return nil, err
}
credentialsParams := google.CredentialsParams{Scopes: config.Scopes, State: state, AuthHandler: func(authCodeURL string) (string, string, error) {
fmt.Println(authCodeURL + "&access_type=offline&prompt=consent")
var callback string
_, err := fmt.Scan(&callback)
u, _ := url.Parse(callback)
fmt.Println()
return u.Query().Get("code"), state, err
}, PKCE: &pkceParams}
credentials, err := google.CredentialsFromJSONWithParams(context.Background(), []byte(configJSON), credentialsParams)
if err != nil {
return nil, err
}
token, err := credentials.TokenSource.Token()
if err != nil {
return nil, err
}
tokenFileJSON, _ := json.Marshal(token)
os.WriteFile(e.OAuth+".token", tokenFileJSON, os.ModePerm)
log.Printf("%s", tokenFileJSON)
}
var tokenStruct struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
Expiry time.Time `json:"expiry"`
ExpiresIn int `json:"expires_in"`
}
token, _ := os.ReadFile(e.OAuth + ".token")
json.Unmarshal(token, &tokenStruct)
if time.Until(tokenStruct.Expiry) < time.Minute*5 {
var appStruct struct {
Installed struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
GrantType string `json:"grant_type"`
RefreshToken string `json:"refresh_token"`
} `json:"installed"`
}
json.Unmarshal([]byte(configJSON), &appStruct)
appStruct.Installed.GrantType = "refresh_token"
appStruct.Installed.RefreshToken = tokenStruct.RefreshToken
b, _ := json.Marshal(appStruct.Installed)
resp, err := http.Post(`https://oauth2.googleapis.com/token`, `application/json`, bytes.NewReader(b))
if err != nil {
return nil, err
}
defer resp.Body.Close()
b, _ = io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("(%d) %s", resp.StatusCode, b)
}
tokenStruct.Expiry = time.Time{}
json.Unmarshal(b, &tokenStruct)
tokenStruct.Expiry = time.Now().Add(time.Duration(tokenStruct.ExpiresIn) * time.Second)
tokenStruct.RefreshToken = appStruct.Installed.RefreshToken
b, _ = json.Marshal(tokenStruct)
os.WriteFile(e.OAuth+".token", b, os.ModePerm)
}
log.Println("OAUTH", e.From, time.Until(tokenStruct.Expiry), tokenStruct.AccessToken)
return e.readIMAP(e.From, tokenStruct.AccessToken)
}
func (e *Emailer) configJSON() (string, error) {
b, err := os.ReadFile(e.OAuth)
return string(b), err
}
func (e *Emailer) readIMAP(authU, authP string) (chan *mail.Message, error) {
c, err := client.DialTLS(e.IMAP, nil)
if err != nil {
return nil, err
}
if err := c.Login(e.From, e.Password); err != nil {
return nil, err
if e.OAuth == "" {
if err := c.Login(authU, authP); err != nil {
return nil, err
}
} else {
if err := c.Authenticate(sasl.NewOAuthBearerClient(&sasl.OAuthBearerOptions{
Username: authU,
Token: authP,
Host: "",
Port: 0,
})); err != nil {
return nil, err
}
}
mbox, err := c.Select("INBOX", true) //readonly
mbox, err := c.Select(e.Inbox, true) //readonly
if err != nil {
return nil, err
}
@@ -86,23 +205,35 @@ func (e *Emailer) ReadIMAP() (chan *mail.Message, error) {
}
func (e *Emailer) ReadPOP3() (chan *mail.Message, error) {
emails := []*mail.Message{}
limit := e.Limit
if limit < 1 {
limit = 1000
}
emails := make(chan *mail.Message, limit)
defer close(emails)
log.Printf("pop3.DialTLS(%s)", e.POP3)
c, err := pop3.DialTLS(e.POP3)
if err != nil {
return nil, err
}
defer c.Rset()
log.Printf("c.Auth(%s, xyz)", e.From)
if err := c.Auth(e.From, e.Password); err != nil {
return nil, err
}
log.Printf("c.ListAll()")
ids, _, err := c.ListAll()
if err != nil {
return nil, err
}
for j, id := range ids {
if e.Limit > 0 && len(ids)-1-j >= e.Limit {
break
}
log.Printf("/c.ListAll() = %v", ids)
for i := len(ids) - 1; i >= 0; i-- {
id := ids[i]
log.Printf("c.Retr(%v)", id)
raw, err := c.Retr(id)
if err != nil {
return nil, err
@@ -111,10 +242,13 @@ func (e *Emailer) ReadPOP3() (chan *mail.Message, error) {
if err != nil {
return nil, err
}
emails = append(emails, msg)
select {
case emails <- msg:
default:
return emails, nil
}
}
return nil, nil
//return emails, nil //c.Quit()
return emails, nil
}
func (e *Emailer) Send(to, subj, msg string) error {

7
go.mod
View File

@@ -1,13 +1,16 @@
module gogs.inhome.blapointe.com/local-sandbox/contact
module gitea.inhome.blapointe.com/local-sandbox/contact
go 1.17
go 1.24.0
require (
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e
github.com/emersion/go-imap v1.2.0
github.com/google/uuid v1.6.0
golang.org/x/oauth2 v0.35.0
)
require (
cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
golang.org/x/text v0.3.7 // indirect
)

6
go.sum
View File

@@ -1,3 +1,5 @@
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e h1:mQTN05gz0rDZSABqKMzAPMb5ATWcvvdMljRzEh0LjBo=
github.com/bytbox/go-pop3 v0.0.0-20120201222208-3046caf0763e/go.mod h1:alXX+s7a4cKaIprgjeEboqi4Tm7XR/HXEwUTxUV/ywU=
github.com/emersion/go-imap v1.2.0 h1:lyUQ3+EVM21/qbWE/4Ya5UG9r5+usDxlg4yfp3TgHFA=
@@ -6,6 +8,10 @@ github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwd
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=