Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reply issue by email #13585

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
404ae49
reply issue by email
a1012112796 Nov 16, 2020
61b9c64
fix vendor
a1012112796 Nov 16, 2020
539421d
Merge branch 'master' into imap
a1012112796 Nov 17, 2020
ca8a716
fix charsets
a1012112796 Nov 17, 2020
30d3479
Merge branch 'master' into imap
a1012112796 Nov 17, 2020
d5dac5d
Merge branch 'master' into imap
a1012112796 Nov 18, 2020
c95f015
simplify logic
a1012112796 Nov 18, 2020
e357517
Merge branch 'master' into imap
a1012112796 Nov 18, 2020
e6ada29
fix test
a1012112796 Nov 18, 2020
4800de2
Merge branch 'master' into imap
a1012112796 Nov 22, 2020
5b5fb6c
Merge branch 'master' into imap
a1012112796 Nov 29, 2020
77cedeb
Merge branch 'master' into imap
a1012112796 Jan 13, 2021
074e6d2
translate
a1012112796 Jan 14, 2021
4baedb5
Merge branch 'master' into imap
a1012112796 Jan 14, 2021
08345f0
add missing config example
a1012112796 Jan 14, 2021
560f48a
Merge branch 'master' into imap
a1012112796 Jan 19, 2021
f30caf9
test code 1 and fix some logic
a1012112796 Jan 19, 2021
f076123
Merge branch 'master' into imap
a1012112796 Jan 19, 2021
b00df2e
lint
a1012112796 Jan 19, 2021
47df1c9
fix bug
a1012112796 Jan 19, 2021
2923155
Merge branch 'main' into imap
a1012112796 May 7, 2021
4176a92
fix bug
a1012112796 May 7, 2021
e881e4c
Merge branch 'main' into imap
a1012112796 Nov 12, 2021
cffb646
apply suggestions from code review
a1012112796 Nov 13, 2021
99921b3
Merge branch 'main' into imap
a1012112796 Nov 13, 2021
65c26ca
fix lint
a1012112796 Nov 13, 2021
68c69bb
Merge branch 'main' into imap
a1012112796 Nov 14, 2021
4069ceb
fix ci and remove test code before finish it
a1012112796 Nov 14, 2021
3cfe21e
Merge branch 'main' into imap
a1012112796 Nov 14, 2021
325392e
upgrade go-imap v1.0.6 -> v1.2.0
a1012112796 Nov 14, 2021
5589c19
fix lint
a1012112796 Nov 14, 2021
e1948eb
Merge branch 'main' into imap
a1012112796 Nov 17, 2021
fe2f5e6
test code 1
a1012112796 Nov 17, 2021
9670bc1
fmt
a1012112796 Nov 18, 2021
0fc7000
Merge branch 'main' into imap
a1012112796 Nov 18, 2021
f0d9b54
fix lint
a1012112796 Nov 18, 2021
0bad64a
Merge branch 'main' into imap
a1012112796 Nov 18, 2021
bbb2513
remove not passd test before fix
a1012112796 Nov 18, 2021
af5a825
fmt
a1012112796 Nov 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ Gitea or set your environment appropriately.`, "")
}
}

supportProcRecive := false
supportProcReceive := false
if git.CheckGitVersionAtLeast("2.29") == nil {
supportProcRecive = true
supportProcReceive = true
}

for scanner.Scan() {
Expand All @@ -241,9 +241,9 @@ Gitea or set your environment appropriately.`, "")
lastline++

// If the ref is a branch or tag, check if it's protected
// if supportProcRecive all ref should be checked because
// if supportProcReceive all ref should be checked because
// permission check was delayed
if supportProcRecive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
if supportProcReceive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
oldCommitIDs[count] = oldCommitID
newCommitIDs[count] = newCommitID
refFullNames[count] = refFullName
Expand Down
35 changes: 35 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,30 @@ PATH =
;; Timeout for Sendmail
;SENDMAIL_TIMEOUT = 5m

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[mail_receive]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;ENABLED = false
;; Buffer length of channel, keep it as it is if you don't know what it is.
;READ_BUFFER_LEN = 100
;; email address to receive mail
;RECEIVE_EMAIL =
;; receive email box
;RECEIVE_BOX = INBOX
;; Mail server
;; Gmail: imap.gmail.com:993
;; QQ: imap.qq.com:993
;; Outlook: outlook.office365.com:993
;HOST =
;USER =
;PASSWD =
;IS_TLS_ENABLED = true
;; delete mail after read
;DELETE_READ_MAIL = false

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cache]
Expand Down Expand Up @@ -1945,6 +1969,17 @@ PATH =
;SCHEDULE = @every 168h
;HTTP_ENDPOINT = https://dl.gitea.io/gitea/version.json

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; fetch unread mails
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cron.imap_fetch_mails]
;; when [mail_receive] is enabled, this will be enabled automatically as well
;ENABLED = false
;RUN_AT_START = false
;NO_SUCCESS_NOTICE = false
;SCHEDULE = @every 5m

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Git Operation timeout in seconds
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ require (
github.com/djherbis/nio/v3 v3.0.1
github.com/dustin/go-humanize v1.0.0
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2
github.com/emersion/go-imap v1.2.0
github.com/emersion/go-message v0.15.0
github.com/emirpasic/gods v1.12.0
github.com/ethantkoenig/rupture v1.0.0
github.com/gliderlabs/ssh v0.3.3
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,14 @@ github.com/editorconfig/editorconfig-core-go/v2 v2.4.2 h1:1lkDpSoAaFLrgYTVJ/eNCV
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2/go.mod h1:IXeWRVO4LZRoNunhHh/oP6BQvTs94nB2pNvbw32l8tQ=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
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 h1:urgKGqt2JAc9NFJcgncQcohHdiYb803YTH9OQwHBHIY=
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-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
Expand Down
1 change: 0 additions & 1 deletion models/fixtures/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
created_unix: 946684810
updated_unix: 978307190


-
id: 3
repo_id: 1
Expand Down
17 changes: 17 additions & 0 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -426,6 +427,22 @@ func (issue *Issue) HasLabel(labelID int64) bool {
return issue.hasLabel(db.GetEngine(db.DefaultContext), labelID)
}

// ReplyReference returns tokenized address to use for email reply headers
func (issue *Issue) ReplyReference(key string) string {
var path string
if issue.IsPull {
path = "pulls"
} else {
path = "issues"
}

if len(key) > 0 {
return fmt.Sprintf("%s/%s/%d/%s@%s", issue.Repo.FullName(), path, issue.Index, key, setting.Domain)
}

return fmt.Sprintf("%s/%s/%d@%s", issue.Repo.FullName(), path, issue.Index, setting.Domain)
}

func (issue *Issue) addLabel(e db.Engine, label *Label, doer *User) error {
return newIssueLabel(e, issue, label, doer)
}
Expand Down
38 changes: 38 additions & 0 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"

Expand Down Expand Up @@ -713,6 +714,43 @@ func (c *Comment) LoadPushCommits() (err error) {
return err
}

// ReplyReference returns tokenized address to use for email reply headers
func (c *Comment) ReplyReference(key string) string {
if err := c.LoadIssue(); err != nil {
log.Error("comment.LoadIssue(): %v", err)
return ""
}

if err := c.Issue.LoadRepo(); err != nil {
log.Error("Issue.LoadRepo(): %v", err)
return ""
}

var path string
if c.Issue.IsPull {
path = "pulls"
} else {
path = "issues"
}

if len(key) > 0 {
return fmt.Sprintf("%s/%s/%d/comment/%d/%s@%s",
c.Issue.Repo.FullName(),
path,
c.Issue.Index,
c.ID,
key,
setting.Domain)
}

return fmt.Sprintf("%s/%s/%d/comment/%d@%s",
c.Issue.Repo.FullName(),
path,
c.Issue.Index,
c.ID,
setting.Domain)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, these Message-ID should follow RFC encoding


func createComment(e db.Engine, opts *CreateCommentOptions) (_ *Comment, err error) {
var LabelID int64
if opts.Label != nil {
Expand Down
2 changes: 1 addition & 1 deletion models/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func CreateRepoTransferNotification(doer, newOwner *User, repo *Repository) erro

// CreateOrUpdateIssueNotifications creates an issue notification
// for each watcher, or updates it if already exists
// receiverID > 0 just send to reciver, else send to all watcher
// receiverID > 0 just send to receiver, else send to all watcher
func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error {
sess := db.NewSession(db.DefaultContext)
defer sess.Close()
Expand Down
2 changes: 1 addition & 1 deletion modules/base/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func EncodeSha1(str string) string {
return hex.EncodeToString(h.Sum(nil))
}

// EncodeSha256 string to sha1 hex value.
// EncodeSha256 string to sha256 hex value.
func EncodeSha256(str string) string {
h := sha256.New()
_, _ = h.Write([]byte(str))
Expand Down
44 changes: 44 additions & 0 deletions modules/setting/mail_receive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package setting

import "code.gitea.io/gitea/modules/log"

// MailReceiver represents mail receive service.
type MailReceiver struct {
ReceiveEmail string
ReceiveBox string
QueueLength int
Host string
User, Passwd string
IsTLSEnabled bool
DeleteReadMail bool
}

var (
// MailRecieveService mail receive config
MailRecieveService *MailReceiver
)

func newMailRecieveService() {
sec := Cfg.Section("mail_receive")
// Check mailer setting.
if !sec.Key("ENABLED").MustBool() {
return
}

MailRecieveService = &MailReceiver{
ReceiveEmail: sec.Key("RECEIVE_EMAIL").String(),
ReceiveBox: sec.Key("RECEIVE_BOX").MustString("INBOX"),
QueueLength: sec.Key("READ_BUFFER_LEN").MustInt(100),
Host: sec.Key("HOST").String(),
User: sec.Key("USER").String(),
Passwd: sec.Key("PASSWD").String(),
IsTLSEnabled: sec.Key("IS_TLS_ENABLED").MustBool(true),
DeleteReadMail: sec.Key("DELETE_READ_MAIL").MustBool(false),
}

log.Info("Mail Receive Service Enabled")
}
1 change: 1 addition & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ func NewServices() {
newSessionService()
newCORSService()
newMailService()
newMailRecieveService()
newRegisterMailService()
newNotifyMailService()
newProxyService()
Expand Down
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2347,6 +2347,8 @@ dashboard.last_gc_pause = Last GC Pause
dashboard.gc_times = GC Times
dashboard.delete_old_actions = Delete all old actions from database
dashboard.delete_old_actions.started = Delete all old actions from database started.
dashboard.imap_fetch_mails = fetch unread mails
dashboard.imap_fetch_mails.started = Started fetching unread mails.

users.user_manage_panel = User Account Management
users.new_account = Create User Account
Expand Down
6 changes: 4 additions & 2 deletions routers/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ import (
"code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/cron"
"code.gitea.io/gitea/services/imap"
"code.gitea.io/gitea/services/mailer"
repo_migrations "code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror"
"code.gitea.io/gitea/services/mirror"
pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/services/task"
Expand Down Expand Up @@ -118,6 +119,7 @@ func GlobalInit(ctx context.Context) {

InitGitServices()
mailer.NewContext()
imap.NewContext()
mustInit(cache.NewContext)
notification.NewContext()
mustInit(archiver.Init)
Expand Down Expand Up @@ -145,7 +147,7 @@ func GlobalInit(ctx context.Context) {
code_indexer.Init()
mustInit(stats_indexer.Init)

mirror_service.InitSyncMirrors()
mirror.InitSyncMirrors()
webhook.InitDeliverHooks()
mustInit(pull_service.Init)
mustInit(task.Init)
Expand Down
2 changes: 1 addition & 1 deletion routers/private/hook_proc_receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func HookProcReceive(ctx *gitea_context.PrivateContext) {
return
}

results := agit.ProcRecive(ctx, opts)
results := agit.ProcReceive(ctx, opts)
if ctx.Written() {
return
}
Expand Down
4 changes: 2 additions & 2 deletions services/agit/agit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
pull_service "code.gitea.io/gitea/services/pull"
)

// ProcRecive handle proc receive work
func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []private.HookProcReceiveRefResult {
// ProcReceive handle proc receive work
func ProcReceive(ctx *context.PrivateContext, opts *private.HookOptions) []private.HookProcReceiveRefResult {
// TODO: Add more options?
var (
topicBranch string
Expand Down
12 changes: 12 additions & 0 deletions services/cron/tasks_extended.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/updatechecker"
"code.gitea.io/gitea/services/imap"
repo_service "code.gitea.io/gitea/services/repository"
)

Expand Down Expand Up @@ -133,6 +134,16 @@ func registerDeleteOldActions() {
})
}

func registerImapFetchUnreadMails() {
RegisterTaskFatal("imap_fetch_mails", &BaseConfig{
Enabled: setting.MailRecieveService != nil,
RunAtStart: false,
Schedule: "@every 5m",
}, func(ctx context.Context, _ *models.User, _ Config) error {
return imap.FetchAllUnreadMails()
})
}

func registerUpdateGiteaChecker() {
type UpdateCheckerConfig struct {
BaseConfig
Expand Down Expand Up @@ -163,4 +174,5 @@ func initExtendedTasks() {
registerRemoveRandomAvatars()
registerDeleteOldActions()
registerUpdateGiteaChecker()
registerImapFetchUnreadMails()
}
46 changes: 46 additions & 0 deletions services/imap/cron.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package imap

import (
"code.gitea.io/gitea/modules/setting"
)

var (
c *Client
)

// FetchAllUnreadMails fetch all unread mails
func FetchAllUnreadMails() (err error) {
if c == nil {
c, err = NewImapClient(ClientInitOpt{
Addr: setting.MailRecieveService.Host,
UserName: setting.MailRecieveService.User,
Passwd: setting.MailRecieveService.Passwd,
IsTLS: setting.MailRecieveService.IsTLSEnabled,
})
if err != nil {
return
}
}

if mailReadQueue != nil && !mailReadQueue.IsEmpty() {
return
}

mails, err := c.GetUnreadMails(setting.MailRecieveService.ReceiveBox, 100)
if err != nil {
return
}

for _, mail := range mails {
err = mailReadQueue.Push(mail)
if err != nil {
return err
}
}

return nil
}
Loading