user gomail and new activate account email tpl

- #1496: fallback plain text
- #1002: add date header
- #913: fix encoding of header
This commit is contained in:
Unknwon committed 2015-09-17 01:54:12 -04:00
1 parent e75fd2f783
commit 373731f5e8
16 files changed
+187 -302

No files matched your search

+1
View File
@@ -33,6 +33,7 @@ github.com/russross/blackfriday = commit:8cec3a854e
github.com/shurcooL/sanitized_anchor_name = commit:244f5ac324
golang.org/x/net =
golang.org/x/text =
gopkg.in/gomail.v2 =
gopkg.in/ini.v1 = commit:463307112d
gopkg.in/redis.v2 = commit:e617904962
+5
View File
@@ -160,6 +160,11 @@ invalid_code = Sorry, your confirmation code has expired or not valid.
reset_password_helper = Click here to reset your password
password_too_short = Password length cannot be less then 6.
[mail]
register_success = Register success, Welcome
activate_account = Please activate your account
activate_email = Verify your e-mail address
[modal]
yes = Yes
no = No
+16
View File
@@ -133,6 +133,22 @@ func (u *User) HomeLink() string {
return setting.AppSubUrl + "/" + u.Name
}
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
func (u *User) GenerateEmailActivateCode(email string) string {
code := base.CreateTimeLimitCode(
com.ToStr(u.Id)+email+u.LowerName+u.Passwd+u.Rands,
setting.Service.ActiveCodeLives, nil)
// Add tail hex username
code += hex.EncodeToString([]byte(u.LowerName))
return code
}
// GenerateActivateCode generates an activate code based on user information.
func (u *User) GenerateActivateCode() string {
return u.GenerateEmailActivateCode(u.Email)
}
// CustomAvatarPath returns user custom avatar file path.
func (u *User) CustomAvatarPath() string {
return filepath.Join(setting.AvatarUploadPath, com.ToStr(u.Id))
+2 -2
View File
@@ -4364,7 +4364,7 @@ func confLocaleLocale_deDeIni() (*asset, error) {
return a, nil
}
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xc4\xbd\xeb\x72\xdc\xc8\x8e\x27\xfe\x9d\x4f\xc1\xf6\x84\xff\xee\x8e\x90\xcb\xd1\xdd\xff\xbd\x44\x47\xdb\xbd\xb2\xd4\xbe\xcc\x58\x96\xc6\x52\x9f\xb3\x67\x1d\x8e\x6a\x56\x91\xaa\xe2\x71\x15\x59\x4d\xb2\x2c\xeb\x4c\x4c\xc4\xbe\xc6\xbe\xde\x3e\xc9\x02\x3f\x00\x79\x23\x4b\xb2\xcf\x99\xd8\xfd\x22\xb1\x32\x91\x37\x24\x12\x09\x20\x91\xc8\x62\xb7\x9b\x97\x55\xbf\xcc\x9f\xe6\xc7\xf9\xae\xa8\x9b\x4d\xd5\xf7\x79\x5f\x6d\xae\x1f\xaf\xdb\x7e\xa8\xca\xfc\x65\x3d\xd0\xef\xee\x53\xbd\xac\xb2\x6c\xdd\x6e\x2b\x02\x7d\x45\xff\xb2\xb2\xe8\xd7\x8b\xb6\xe8\x4a\x4a\x38\xb5\xef\xac\xfa\xbc\xdb\xb4\x1d\x03\xfd\x2a\x5f\xd9\xba\xda\xec\xb8\x0c\xfd\xcb\xfa\x7a\xd5\xcc\xeb\x86\x7e\x5e\xd2\x57\xfe\xba\xc9\xfa\x76\x59\x17\x9b\x79\x90\x81\x04\xcb\xff\x29\xff\xa1\x29\xf3\xcb\xa1\xda\xe5\x3f\xf7\xdb\x62\xb3\x79\x56\xf4\x28\x32\x54\x79\xb1\x5c\xb6\xfb\x66\xf8\xf9\x89\x64\x48\xe5\xed\x7e\xb0\xda\xcf\xf7\x83\xa4\xed\x77\x96\xf4\xdb\x2e\xeb\xaa\x55\x4d\x03\xeb\x28\xe9\x9d\x7e\x66\x37\xd5\xa2\xaf\x07\xee\xf4\x9f\xe5\x2b\xfb\x54\x75\x7d\xdd\x72\x7f\xfe\x24\x5f\xd9\xae\x58\x31\xc0\x05\xfd\xcb\x86\x6a\xbb\xdb\x14\x28\x70\xa5\x9f\xd9\xa6\x68\x56\x7b\x81\x79\xa3\x9f\xd9\xb2\xab\x28\x6b\xde\x54\x37\x94\x7a\x82\x1f\xb3\xd9\x2c\xdb\x13\x3e\xe7\xbb\xae\xbd\xae\x37\xd5\xbc\x68\xca\xf9\x56\x30\xf6\x1b\xa5\xe7\x9a\x9e\x53\x7a\xce\xe9\x18\x42\x55\x12\x72\xe6\x45\xaf\xe3\xa0\x69\x21\x5c\x15\x7d\x86\xaa\x9a\x62\x6b\xa5\xf9\x33\xab\xb6\x45\xbd\xe1\x09\x78\xcc\x1f\xd4\xf1\xbe\xbf\x69\x31\x4d\x17\xfa\x49\x48\x98\x0f\xb7\xbb\x0a\x38\x78\x7c\x45\x5f\xd9\xb2\xd8\x0d\xcb\x75\xc1\xfd\x94\xaf\x8c\x80\x76\x2d\x21\xa3\xed\x6e\x01\x67\x3f\xb2\xb6\x5b\x15\x4d\xfd\xb7\x62\x10\x04\x9d\x07\x3f\xb3\x6d\xdd\x75\x2d\xe3\xf6\x0c\x1f\x19\x0d\x7d\xce\xf5\x50\xca\x5b\xc2\x42\x50\x0b\xe7\x6c\xeb\x55\x27\x68\xe4\xcc\x33\xfc\xe2\x5a\x38\xef\xba\xed\x3e\x6a\xc6\x0b\xfe\x4c\x8a\x52\x27\x34\x37\x6e\xbf\x68\x08\xf1\x9a\x7b\x86\x1f\x11\x40\x9f\x15\xe5\x96\x50\xb9\x2b\x9a\x8a\x71\x74\xcc\xbf\x08\x2f\xf4\x2b\x53\x7a\x9a\xf7\xd5\x30\xd4\xcd\x8a\x91\x7d\x2c\x49\xf9\xa5\x26\x65\x41\x9e\x4b\xbb\x6d\xf7\x6e\x3a\x29\xfd\x2f\xf4\x33\xbf\x90\x9f\x92\x17\x14\x42\xa6\x2b\xc9\x23\xe9\xe7\xd7\x55\x55\xca\x58\xfa\xfc\x05\x7d\x67\xbb\xfd\x66\x43\x58\xfb\x63\x5f\xf5\x03\x17\xba\xa0\xdf\x34\x7e\xf9\x9d\xd5\x7d\x4f\x1f\x94\xfc\x1a\x1f\x19\x4d\x5d\xb3\xc4\x60\x4e\xf0\x91\x65\xef\xfb\xaa\xe8\x96\xeb\x0f\x99\xfc\x47\x5f\xf9\x83\x69\xef\xd0\xa4\x32\x21\x29\x11\x49\x0b\xd6\x40\xb6\x6c\x4b\xfe\x71\x42\xff\xa8\xea\xba\xe9\x07\x5a\x6d\x1f\x32\xfd\x60\x30\xf9\x92\x09\x18\xea\x01\x58\xd0\x44\x2c\xdd\x9e\x67\x30\x7f\x51\x77\xfd\xf0\x78\xa8\x89\x58\xdf\xed\x9b\x8c\xc7\x47\x2b\x6d\x5e\x2e\x8c\x01\xbd\x6c\x09\x45\x48\xee\x68\x7c\x67\xb7\x97\xff\xfa\xe6\x28\xbf\x20\x2e\xb4\xea\x2a\x7c\xd3\x1f\x2a\xf1\x63\x4e\x95\x5d\xd5\xa7\xcf\x67\x19\x95\xb5\xf6\x4e\x8b\xa1\x58\x14\x7d\xe5\x91\xcb\x99\x42\xe3\x2e\x0f\x94\xce\x7c\x0d\x3c\xac\x1f\xa2\x51\x4f\xad\x13\xaa\x43\x57\x97\xab\xe3\x2d\x2f\x31\x4a\x67\xb6\x86\xc2\x17\x9b\x8a\xd3\xa9\xaa\xfc\xf5\xdb\xb7\xe7\xa7\xcf\xf3\xaa\x59\xd5\x4d\x95\xdf\xd4\xc3\x3a\xdf\x0f\xd7\xff\x75\xbe\xaa\x9a\xaa\x23\x2e\xb7\xac\x73\x5a\x59\x1d\xd1\x43\x4e\xe4\x2d\x43\x9c\x65\x7d\xbf\x21\x0e\x00\x24\x5f\x5e\xbe\xc9\xcf\x18\xd1\xbb\x62\x58\xa3\x23\xc3\x3a\xeb\xff\xd8\x30\xa2\x5c\x83\x57\xeb\x2a\x07\xad\x01\xa8\xbd\x4e\xf1\x92\x97\xda\xd7\x59\x56\x75\xdd\x9c\x18\xd4\x70\xcb\x68\xd6\x3a\x0f\x41\x4b\x75\x44\x4c\x4d\x3b\xe4\x8b\x2a\x47\x39\xa9\xa2\x6e\x3e\x15\x9b\xba\x24\x64\x7b\x84\xc4\x65\x91\x58\xb6\x34\x6f\x5c\x9a\x26\xbe\xbd\xc1\x50\x8b\x25\xf1\xd7\x3e\x7f\x30\x7b\x00\x86\xf6\xe0\xf1\x83\x59\xd6\xb4\x73\x59\x84\xcc\xfa\xca\xba\x2f\x16\xc4\x06\x85\x2d\x77\xc6\x54\x68\x9d\x58\x57\x14\x22\x8f\x20\x18\xb7\xcc\xea\xc1\x61\x69\xba\xa9\xf6\x1c\x95\xda\xae\x10\x8e\xdd\x96\xbc\x9b\x5f\x59\xf5\x2e\x61\x34\xe6\xcc\x26\xcc\xa8\xeb\x78\xb7\xdb\xd4\x4b\x69\xfa\xa5\xe4\x79\x42\xe3\x3d\x54\x91\x12\xc2\x81\x50\x2c\x2f\x20\x17\xea\x35\x73\x85\x3c\x62\xa3\x28\xbf\xae\x68\x1b\x58\xef\x57\xc2\xfc\x37\xed\xbe\xfc\x06\xeb\xd5\x66\xce\x2f\xd7\xfc\x5d\x4b\x1d\x06\x75\x38\x00\xdf\xc4\x31\xad\x3b\xde\xb6\xbb\x6a\xdb\x0e\x8c\x38\x2d\x56\xd3\xf4\xdc\xd4\x94\x49\x23\xed\x8b\x4f\xc4\x75\x86\x36\x1f\xd6\x75\x4f\x38\xee\xaa\x25\x57\x4c\x0c\x62\x4f\x1b\xa6\x2c\x0b\x5a\xa6\xb2\x34\x2c\x2d\xa6\x41\x40\x6d\xf7\xb4\x9a\xd6\x54\x19\x23\x9e\x65\x07\xaa\x72\xaa\x9f\x18\x12\xd5\x83\x55\x4e\x2b\xb7\xa5\xbd\x89\x27\xfa\x14\x1f\xfa\x3b\xac\x9f\x7a\x55\x5c\x5f\x53\xaf\x7a\x5a\x15\xaf\xf2\xe5\xa6\xa5\x25\xf5\xdb\xbb\x37\x3d\x2f\x98\xf5\x7c\xd7\x76\xd8\xe8\x29\xeb\x82\x3e\x5d\x5a\x80\x68\x86\x68\xf6\xdb\x05\xfd\xba\x59\xd7\xc4\x07\x81\x76\x2e\xc1\xf2\x0c\xa5\x52\x13\xfb\x9e\xa6\xf0\x28\xa7\x25\x4c\x23\x20\x94\x81\x00\x78\x0c\x46\x75\x0c\x7e\x4d\x34\xb6\xef\x68\x39\xad\x87\x61\x67\x2d\xbf\xba\xba\xba\x90\xa6\x5d\xea\x5d\x6d\x17\x01\x65\x60\x0e\x36\x2c\x7a\x34\x79\xdb\xcc\x40\x24\xfb\x6e\x93\xd0\x0f\x8d\xd5\x72\x0e\xe0\x85\xbb\xf0\x84\xff\x5c\x7a\xf4\x00\xcf\x3d\xc9\x67\x37\xaLine truncated
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xc4\xbd\xeb\x72\xdc\xc8\x8e\x27\xfe\x9d\x4f\xc1\xf6\x84\xff\xee\x8e\x90\xcb\xd1\xdd\xff\xbd\x44\x47\xdb\xbd\xb2\xd4\xbe\xcc\x58\x96\xc6\x52\x9f\xb3\x67\x1d\x8e\x6a\x56\x91\xaa\xe2\x71\x15\x59\x4d\xb2\x2c\xeb\x4c\x4c\xc4\xbe\xc6\xbe\xde\x3e\xc9\x02\x3f\x00\x79\x23\x4b\xb2\xcf\x99\xd8\xfd\x22\xb1\x32\x91\x37\x24\x12\x09\x20\x91\xc8\x62\xb7\x9b\x97\x55\xbf\xcc\x9f\xe6\xc7\xf9\xae\xa8\x9b\x4d\xd5\xf7\x79\x5f\x6d\xae\x1f\xaf\xdb\x7e\xa8\xca\xfc\x65\x3d\xd0\xef\xee\x53\xbd\xac\xb2\x6c\xdd\x6e\x2b\x02\x7d\x45\xff\xb2\xb2\xe8\xd7\x8b\xb6\xe8\x4a\x4a\x38\xb5\xef\xac\xfa\xbc\xdb\xb4\x1d\x03\xfd\x2a\x5f\xd9\xba\xda\xec\xb8\x0c\xfd\xcb\xfa\x7a\xd5\xcc\xeb\x86\x7e\x5e\xd2\x57\xfe\xba\xc9\xfa\x76\x59\x17\x9b\x79\x90\x81\x04\xcb\xff\x29\xff\xa1\x29\xf3\xcb\xa1\xda\xe5\x3f\xf7\xdb\x62\xb3\x79\x56\xf4\x28\x32\x54\x79\xb1\x5c\xb6\xfb\x66\xf8\xf9\x89\x64\x48\xe5\xed\x7e\xb0\xda\xcf\xf7\x83\xa4\xed\x77\x96\xf4\xdb\x2e\xeb\xaa\x55\x4d\x03\xeb\x28\xe9\x9d\x7e\x66\x37\xd5\xa2\xaf\x07\xee\xf4\x9f\xe5\x2b\xfb\x54\x75\x7d\xdd\x72\x7f\xfe\x24\x5f\xd9\xae\x58\x31\xc0\x05\xfd\xcb\x86\x6a\xbb\xdb\x14\x28\x70\xa5\x9f\xd9\xa6\x68\x56\x7b\x81\x79\xa3\x9f\xd9\xb2\xab\x28\x6b\xde\x54\x37\x94\x7a\x82\x1f\xb3\xd9\x2c\xdb\x13\x3e\xe7\xbb\xae\xbd\xae\x37\xd5\xbc\x68\xca\xf9\x56\x30\xf6\x1b\xa5\xe7\x9a\x9e\x53\x7a\xce\xe9\x18\x42\x55\x12\x72\xe6\x45\xaf\xe3\xa0\x69\x21\x5c\x15\x7d\x86\xaa\x9a\x62\x6b\xa5\xf9\x33\xab\xb6\x45\xbd\xe1\x09\x78\xcc\x1f\xd4\xf1\xbe\xbf\x69\x31\x4d\x17\xfa\x49\x48\x98\x0f\xb7\xbb\x0a\x38\x78\x7c\x45\x5f\xd9\xb2\xd8\x0d\xcb\x75\xc1\xfd\x94\xaf\x8c\x80\x76\x2d\x21\xa3\xed\x6e\x01\x67\x3f\xb2\xb6\x5b\x15\x4d\xfd\xb7\x62\x10\x04\x9d\x07\x3f\xb3\x6d\xdd\x75\x2d\xe3\xf6\x0c\x1f\x19\x0d\x7d\xce\xf5\x50\xca\x5b\xc2\x42\x50\x0b\xe7\x6c\xeb\x55\x27\x68\xe4\xcc\x33\xfc\xe2\x5a\x38\xef\xba\xed\x3e\x6a\xc6\x0b\xfe\x4c\x8a\x52\x27\x34\x37\x6e\xbf\x68\x08\xf1\x9a\x7b\x86\x1f\x11\x40\x9f\x15\xe5\x96\x50\xb9\x2b\x9a\x8a\x71\x74\xcc\xbf\x08\x2f\xf4\x2b\x53\x7a\x9a\xf7\xd5\x30\xd4\xcd\x8a\x91\x7d\x2c\x49\xf9\xa5\x26\x65\x41\x9e\x4b\xbb\x6d\xf7\x6e\x3a\x29\xfd\x2f\xf4\x33\xbf\x90\x9f\x92\x17\x14\x42\xa6\x2b\xc9\x23\xe9\xe7\xd7\x55\x55\xca\x58\xfa\xfc\x05\x7d\x67\xbb\xfd\x66\x43\x58\xfb\x63\x5f\xf5\x03\x17\xba\xa0\xdf\x34\x7e\xf9\x9d\xd5\x7d\x4f\x1f\x94\xfc\x1a\x1f\x19\x4d\x5d\xb3\xc4\x60\x4e\xf0\x91\x65\xef\xfb\xaa\xe8\x96\xeb\x0f\x99\xfc\x47\x5f\xf9\x83\x69\xef\xd0\xa4\x32\x21\x29\x11\x49\x0b\xd6\x40\xb6\x6c\x4b\xfe\x71\x42\xff\xa8\xea\xba\xe9\x07\x5a\x6d\x1f\x32\xfd\x60\x30\xf9\x92\x09\x18\xea\x01\x58\xd0\x44\x2c\xdd\x9e\x67\x30\x7f\x51\x77\xfd\xf0\x78\xa8\x89\x58\xdf\xed\x9b\x8c\xc7\x47\x2b\x6d\x5e\x2e\x8c\x01\xbd\x6c\x09\x45\x48\xee\x68\x7c\x67\xb7\x97\xff\xfa\xe6\x28\xbf\x20\x2e\xb4\xea\x2a\x7c\xd3\x1f\x2a\xf1\x63\x4e\x95\x5d\xd5\xa7\xcf\x67\x19\x95\xb5\xf6\x4e\x8b\xa1\x58\x14\x7d\xe5\x91\xcb\x99\x42\xe3\x2e\x0f\x94\xce\x7c\x0d\x3c\xac\x1f\xa2\x51\x4f\xad\x13\xaa\x43\x57\x97\xab\xe3\x2d\x2f\x31\x4a\x67\xb6\x86\xc2\x17\x9b\x8a\xd3\xa9\xaa\xfc\xf5\xdb\xb7\xe7\xa7\xcf\xf3\xaa\x59\xd5\x4d\x95\xdf\xd4\xc3\x3a\xdf\x0f\xd7\xff\x75\xbe\xaa\x9a\xaa\x23\x2e\xb7\xac\x73\x5a\x59\x1d\xd1\x43\x4e\xe4\x2d\x43\x9c\x65\x7d\xbf\x21\x0e\x00\x24\x5f\x5e\xbe\xc9\xcf\x18\xd1\xbb\x62\x58\xa3\x23\xc3\x3a\xeb\xff\xd8\x30\xa2\x5c\x83\x57\xeb\x2a\x07\xad\x01\xa8\xbd\x4e\xf1\x92\x97\xda\xd7\x59\x56\x75\xdd\x9c\x18\xd4\x70\xcb\x68\xd6\x3a\x0f\x41\x4b\x75\x44\x4c\x4d\x3b\xe4\x8b\x2a\x47\x39\xa9\xa2\x6e\x3e\x15\x9b\xba\x24\x64\x7b\x84\xc4\x65\x91\x58\xb6\x34\x6f\x5c\x9a\x26\xbe\xbd\xc1\x50\x8b\x25\xf1\xd7\x3e\x7f\x30\x7b\x00\x86\xf6\xe0\xf1\x83\x59\xd6\xb4\x73\x59\x84\xcc\xfa\xca\xba\x2f\x16\xc4\x06\x85\x2d\x77\xc6\x54\x68\x9d\x58\x57\x14\x22\x8f\x20\x18\xb7\xcc\xea\xc1\x61\x69\xba\xa9\xf6\x1c\x95\xda\xae\x10\x8e\xdd\x96\xbc\x9b\x5f\x59\xf5\x2e\x61\x34\xe6\xcc\x26\xcc\xa8\xeb\x78\xb7\xdb\xd4\x4b\x69\xfa\xa5\xe4\x79\x42\xe3\x3d\x54\x91\x12\xc2\x81\x50\x2c\x2f\x20\x17\xea\x35\x73\x85\x3c\x62\xa3\x28\xbf\xae\x68\x1b\x58\xef\x57\xc2\xfc\x37\xed\xbe\xfc\x06\xeb\xd5\x66\xce\x2f\xd7\xfc\x5d\x4b\x1d\x06\x75\x38\x00\xdf\xc4\x31\xad\x3b\xde\xb6\xbb\x6a\xdb\x0e\x8c\x38\x2d\x56\xd3\xf4\xdc\xd4\x94\x49\x23\xed\x8b\x4f\xc4\x75\x86\x36\x1f\xd6\x75\x4f\x38\xee\xaa\x25\x57\x4c\x0c\x62\x4f\x1b\xa6\x2c\x0b\x5a\xa6\xb2\x34\x2c\x2d\xa6\x41\x40\x6d\xf7\xb4\x9a\xd6\x54\x19\x23\x9e\x65\x07\xaa\x72\xaa\x9f\x18\x12\xd5\x83\x55\x4e\x2b\xb7\xa5\xbd\x89\x27\xfa\x14\x1f\xfa\x3b\xac\x9f\x7a\x55\x5c\x5f\x53\xaf\x7a\x5a\x15\xaf\xf2\xe5\xa6\xa5\x25\xf5\xdb\xbb\x37\x3d\x2f\x98\xf5\x7c\xd7\x76\xd8\xe8\x29\xeb\x82\x3e\x5d\x5a\x80\x68\x86\x68\xf6\xdb\x05\xfd\xba\x59\xd7\xc4\x07\x81\x76\x2e\xc1\xf2\x0c\xa5\x52\x13\xfb\x9e\xa6\xf0\x28\xa7\x25\x4c\x23\x20\x94\x81\x00\x78\x0c\x46\x75\x0c\x7e\x4d\x34\xb6\xef\x68\x39\xad\x87\x61\x67\x2d\xbf\xba\xba\xba\x90\xa6\x5d\xea\x5d\x6d\x17\x01\x65\x60\x0e\x36\x2c\x7a\x34\x79\xdb\xcc\x40\x24\xfb\x6e\x93\xd0\x0f\x8d\xd5\x72\x0e\xe0\x85\xbb\xf0\x84\xff\x5c\x7a\xf4\x00\xcf\x3d\xc9\x67\x37\xaLine truncated
func confLocaleLocale_enUsIniBytes() ([]byte, error) {
return bindataRead(
@@ -4379,7 +4379,7 @@ func confLocaleLocale_enUsIni() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 43577, mode: os.FileMode(420), modTime: time.Unix(1442448353, 0)}
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 43722, mode: os.FileMode(420), modTime: time.Unix(1442467863, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
+32 -94
View File
@@ -5,12 +5,10 @@
package mailer
import (
"encoding/hex"
"errors"
"fmt"
"path"
"github.com/Unknwon/com"
"github.com/Unknwon/macaron"
"github.com/gogits/gogs/models"
@@ -20,26 +18,16 @@ import (
)
const (
AUTH_ACTIVE base.TplName = "mail/auth/active"
AUTH_ACTIVATE_EMAIL base.TplName = "mail/auth/activate_email"
AUTH_REGISTER_SUCCESS base.TplName = "mail/auth/register_success"
AUTH_ACTIVATE base.TplName = "mail/auth/activate"
AUTH_ACTIVATE_EMAIL base.TplName = "mail/auth/activate_email"
AUTH_RESET_PASSWORD base.TplName = "mail/auth/reset_passwd"
NOTIFY_COLLABORATOR base.TplName = "mail/notify/collaborator"
NOTIFY_MENTION base.TplName = "mail/notify/mention"
)
// Create New mail message use MailFrom and MailUser
func NewMailMessageFrom(To []string, from, subject, body string) Message {
return NewHtmlMessage(To, from, subject, body)
}
// Create New mail message use MailFrom and MailUser
func NewMailMessage(To []string, subject, body string) Message {
return NewMailMessageFrom(To, setting.MailService.From, subject, body)
}
func GetMailTmplData(u *models.User) map[interface{}]interface{} {
func ComposeTplData(u *models.User) map[interface{}]interface{} {
data := make(map[interface{}]interface{}, 10)
data["AppName"] = setting.AppName
data["AppVer"] = setting.AppVer
@@ -52,95 +40,45 @@ func GetMailTmplData(u *models.User) map[interface{}]interface{} {
return data
}
// create a time limit code for user active
func CreateUserActiveCode(u *models.User, startInf interface{}) string {
minutes := setting.Service.ActiveCodeLives
data := com.ToStr(u.Id) + u.Email + u.LowerName + u.Passwd + u.Rands
code := base.CreateTimeLimitCode(data, minutes, startInf)
// add tail hex username
code += hex.EncodeToString([]byte(u.LowerName))
return code
}
// create a time limit code for user active
func CreateUserEmailActivateCode(u *models.User, e *models.EmailAddress, startInf interface{}) string {
minutes := setting.Service.ActiveCodeLives
data := com.ToStr(u.Id) + e.Email + u.LowerName + u.Passwd + u.Rands
code := base.CreateTimeLimitCode(data, minutes, startInf)
// add tail hex username
code += hex.EncodeToString([]byte(u.LowerName))
return code
}
// Send user register mail with active code
func SendRegisterMail(r macaron.Render, u *models.User) {
code := CreateUserActiveCode(u, nil)
subject := "Register success, Welcome"
data := GetMailTmplData(u)
data["Code"] = code
body, err := r.HTMLString(string(AUTH_REGISTER_SUCCESS), data)
func SendActivateAccountMail(c *macaron.Context, u *models.User) {
data := ComposeTplData(u)
data["Code"] = u.GenerateActivateCode()
body, err := c.HTMLString(string(AUTH_ACTIVATE), data)
if err != nil {
log.Error(4, "mail.SendRegisterMail(fail to render): %v", err)
log.Error(4, "HTMLString: %v", err)
return
}
msg := NewMailMessage([]string{u.Email}, subject, body)
msg.Info = fmt.Sprintf("UID: %d, send register mail", u.Id)
msg := NewMessage([]string{u.Email}, c.Tr("mail.activate_account"), body)
msg.Info = fmt.Sprintf("UID: %d, activate account", u.Id)
SendAsync(&msg)
SendAsync(msg)
}
// Send email verify active email.
func SendActiveMail(r macaron.Render, u *models.User) {
code := CreateUserActiveCode(u, nil)
subject := "Verify your e-mail address"
data := GetMailTmplData(u)
data["Code"] = code
body, err := r.HTMLString(string(AUTH_ACTIVE), data)
if err != nil {
log.Error(4, "mail.SendActiveMail(fail to render): %v", err)
return
}
msg := NewMailMessage([]string{u.Email}, subject, body)
msg.Info = fmt.Sprintf("UID: %d, send active mail", u.Id)
SendAsync(&msg)
}
// Send email to verify secondary email.
func SendActivateEmail(r macaron.Render, user *models.User, email *models.EmailAddress) {
code := CreateUserEmailActivateCode(user, email, nil)
subject := "Verify your e-mail address"
data := GetMailTmplData(user)
data["Code"] = code
// SendActivateAccountMail sends confirmation e-mail.
func SendActivateEmailMail(c *macaron.Context, u *models.User, email *models.EmailAddress) {
data := ComposeTplData(u)
data["Code"] = u.GenerateEmailActivateCode(email.Email)
data["Email"] = email.Email
body, err := r.HTMLString(string(AUTH_ACTIVATE_EMAIL), data)
body, err := c.HTMLString(string(AUTH_ACTIVATE_EMAIL), data)
if err != nil {
log.Error(4, "mail.SendActiveMail(fail to render): %v", err)
log.Error(4, "HTMLString: %v", err)
return
}
msg := NewMailMessage([]string{email.Email}, subject, body)
msg.Info = fmt.Sprintf("UID: %d, send activate email to %s", user.Id, email.Email)
msg := NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body)
msg.Info = fmt.Sprintf("UID: %d, activate email: %s", u.Id, email.Email)
SendAsync(&msg)
SendAsync(msg)
}
// Send reset password email.
func SendResetPasswdMail(r macaron.Render, u *models.User) {
code := CreateUserActiveCode(u, nil)
code := u.GenerateActivateCode()
subject := "Reset your password"
data := GetMailTmplData(u)
data := ComposeTplData(u)
data["Code"] = code
body, err := r.HTMLString(string(AUTH_RESET_PASSWORD), data)
if err != nil {
@@ -148,10 +86,10 @@ func SendResetPasswdMail(r macaron.Render, u *models.User) {
return
}
msg := NewMailMessage([]string{u.Email}, subject, body)
msg := NewMessage([]string{u.Email}, subject, body)
msg.Info = fmt.Sprintf("UID: %d, send reset password email", u.Id)
SendAsync(&msg)
SendAsync(msg)
}
// SendIssueNotifyMail sends mail notification of all watchers of repository.
@@ -182,9 +120,9 @@ func SendIssueNotifyMail(u, owner *models.User, repo *models.Repository, issue *
content := fmt.Sprintf("%s<br>-<br> <a href=\"%s%s/%s/issues/%d\">View it on Gogs</a>.",
base.RenderSpecialLink([]byte(issue.Content), owner.Name+"/"+repo.Name),
setting.AppUrl, owner.Name, repo.Name, issue.Index)
msg := NewMailMessageFrom(tos, u.Email, subject, content)
msg := NewMessageFrom(tos, u.Email, subject, content)
msg.Info = fmt.Sprintf("Subject: %s, send issue notify emails", subject)
SendAsync(&msg)
SendAsync(msg)
return tos, nil
}
@@ -198,7 +136,7 @@ func SendIssueMentionMail(r macaron.Render, u, owner *models.User,
subject := fmt.Sprintf("[%s] %s (#%d)", repo.Name, issue.Name, issue.Index)
data := GetMailTmplData(nil)
data := ComposeTplData(nil)
data["IssueLink"] = fmt.Sprintf("%s/%s/issues/%d", owner.Name, repo.Name, issue.Index)
data["Subject"] = subject
@@ -207,9 +145,9 @@ func SendIssueMentionMail(r macaron.Render, u, owner *models.User,
return fmt.Errorf("mail.SendIssueMentionMail(fail to render): %v", err)
}
msg := NewMailMessageFrom(tos, u.Email, subject, body)
msg := NewMessageFrom(tos, u.Email, subject, body)
msg.Info = fmt.Sprintf("Subject: %s, send issue mention emails", subject)
SendAsync(&msg)
SendAsync(msg)
return nil
}
@@ -219,7 +157,7 @@ func SendCollaboratorMail(r macaron.Render, u, owner *models.User,
subject := fmt.Sprintf("%s added you to %s", owner.Name, repo.Name)
data := GetMailTmplData(nil)
data := ComposeTplData(nil)
data["RepoLink"] = path.Join(owner.Name, repo.Name)
data["Subject"] = subject
@@ -228,9 +166,9 @@ func SendCollaboratorMail(r macaron.Render, u, owner *models.User,
return fmt.Errorf("mail.SendCollaboratorMail(fail to render): %v", err)
}
msg := NewMailMessage([]string{u.Email}, subject, body)
msg := NewMessage([]string{u.Email}, subject, body)
msg.Info = fmt.Sprintf("UID: %d, send register mail", u.Id)
SendAsync(&msg)
SendAsync(msg)
return nil
}
+65 -119
View File
@@ -7,16 +7,44 @@ package mailer
import (
"crypto/tls"
"fmt"
"io"
"net"
"net/mail"
"net/smtp"
"os"
"strings"
"time"
"gopkg.in/gomail.v2"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
type Message struct {
Info string // Message information for log purpose.
*gomail.Message
}
// NewMessageFrom creates new mail message object with custom From header.
func NewMessageFrom(to []string, from, subject, body string) *Message {
msg := gomail.NewMessage()
msg.SetHeader("From", from)
msg.SetHeader("To", to...)
msg.SetHeader("Subject", subject)
msg.SetDateHeader("Date", time.Now())
msg.SetBody("text/plain", body)
msg.AddAlternative("text/html", body)
return &Message{
Message: msg,
}
}
// NewMessage creates new mail message object with default From header.
func NewMessage(to []string, subject, body string) *Message {
return NewMessageFrom(to, setting.MailService.From, subject, body)
}
type loginAuth struct {
username, password string
}
@@ -44,74 +72,24 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
return nil, nil
}
type Message struct {
To []string
From string
Subject string
ReplyTo string
Body string
Type string
Massive bool
Info string
type Sender struct {
}
// create mail content
func (m Message) Content() string {
// set mail type
contentType := "text/plain; charset=UTF-8"
if m.Type == "html" {
contentType = "text/html; charset=UTF-8"
}
func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
opts := setting.MailService
// create mail content
content := "From: " + m.From + "\r\nReply-To: " + m.ReplyTo + "\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body
return content
}
var mailQueue chan *Message
func NewContext() {
if setting.MailService == nil {
return
}
mailQueue = make(chan *Message, setting.MailService.QueueLength)
go processMailQueue()
}
func processMailQueue() {
for {
select {
case msg := <-mailQueue:
num, err := Send(msg)
tos := strings.Join(msg.To, ", ")
info := ""
if err != nil {
if len(msg.Info) > 0 {
info = ", info: " + msg.Info
}
log.Error(4, fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err))
} else {
log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info))
}
}
}
}
// sendMail allows mail with self-signed certificates.
func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte) error {
host, port, err := net.SplitHostPort(settings.Host)
host, port, err := net.SplitHostPort(opts.Host)
if err != nil {
return err
}
tlsconfig := &tls.Config{
InsecureSkipVerify: settings.SkipVerify,
InsecureSkipVerify: opts.SkipVerify,
ServerName: host,
}
if settings.UseCertificate {
cert, err := tls.LoadX509KeyPair(settings.CertFile, settings.KeyFile)
if opts.UseCertificate {
cert, err := tls.LoadX509KeyPair(opts.CertFile, opts.KeyFile)
if err != nil {
return err
}
@@ -159,17 +137,16 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte)
}
canAuth, options := client.Extension("AUTH")
if canAuth && len(settings.User) > 0 {
if canAuth && len(opts.User) > 0 {
var auth smtp.Auth
if strings.Contains(options, "CRAM-MD5") {
auth = smtp.CRAMMD5Auth(settings.User, settings.Passwd)
auth = smtp.CRAMMD5Auth(opts.User, opts.Passwd)
} else if strings.Contains(options, "PLAIN") {
auth = smtp.PlainAuth("", settings.User, settings.Passwd, host)
auth = smtp.PlainAuth("", opts.User, opts.Passwd, host)
} else if strings.Contains(options, "LOGIN") {
// Patch for AUTH LOGIN
auth = LoginAuth(settings.User, settings.Passwd)
auth = LoginAuth(opts.User, opts.Passwd)
}
if auth != nil {
@@ -179,15 +156,11 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte)
}
}
if fromAddress, err := mail.ParseAddress(settings.From); err != nil {
if err = client.Mail(from); err != nil {
return err
} else {
if err = client.Mail(fromAddress.Address); err != nil {
return err
}
}
for _, rec := range recipients {
for _, rec := range to {
if err = client.Rcpt(rec); err != nil {
return err
}
@@ -196,71 +169,44 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte)
w, err := client.Data()
if err != nil {
return err
}
if _, err = w.Write([]byte(msgContent)); err != nil {
} else if _, err = msg.WriteTo(w); err != nil {
return err
}
if err = w.Close(); err != nil {
} else if err = w.Close(); err != nil {
return err
}
return client.Quit()
}
// Direct Send mail message
func Send(msg *Message) (int, error) {
log.Trace("Sending mails to: %s", strings.Join(msg.To, ", "))
func processMailQueue() {
sender := &Sender{}
// get message body
content := msg.Content()
if len(msg.To) == 0 {
return 0, fmt.Errorf("empty receive emails")
} else if len(msg.Body) == 0 {
return 0, fmt.Errorf("empty email body")
}
if msg.Massive {
// send mail to multiple emails one by one
num := 0
for _, to := range msg.To {
body := []byte("To: " + to + "\r\n" + content)
err := sendMail(setting.MailService, []string{to}, body)
if err != nil {
return num, err
for {
select {
case msg := <-mailQueue:
log.Trace("New e-mail sending request %s: %s", msg.GetHeader("To"), msg.Info)
if err := gomail.Send(sender, msg.Message); err != nil {
log.Error(4, "Fail to send e-mails %s: %s - %v", msg.GetHeader("To"), msg.Info, err)
} else {
log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info)
}
num++
}
return num, nil
} else {
body := []byte("To: " + strings.Join(msg.To, ",") + "\r\n" + content)
// send to multiple emails in one message
err := sendMail(setting.MailService, msg.To, body)
if err != nil {
return 0, err
} else {
return 1, nil
}
}
}
// Async Send mail message
var mailQueue chan *Message
func NewContext() {
if setting.MailService == nil {
return
}
mailQueue = make(chan *Message, setting.MailService.QueueLength)
go processMailQueue()
}
func SendAsync(msg *Message) {
go func() {
mailQueue <- msg
}()
}
// Create html mail message
func NewHtmlMessage(To []string, From, Subject, Body string) Message {
return Message{
To: To,
From: setting.MailService.From,
ReplyTo: From,
Subject: Subject,
Body: Body,
Type: "html",
}
}
+1 -1
View File
@@ -1 +1 @@
@font-face{font-family:octicons;src:url(../fonts/octicons.eot?#iefix&v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('embedded-opentype'),url(../fonts/octicons.woff?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('woff'),url(../fonts/octicons.ttf?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('truetype'),url(../fonts/octicons.svg?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d#octicons) format('svg');font-weight:400;font-style:normal}.mega-octicon,.octicon{font:normal normal normal 16px/1 octicons;display:inline-block;text-decoration:none;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mega-octicon{font-size:32px}.octicon-alert:before{content:'\f02d'}.octicon-arrow-down:before{content:'\f03f'}.octicon-arrow-left:before{content:'\f040'}.octicon-arrow-right:before{content:'\f03e'}.octicon-arrow-small-down:before{content:'\f0a0'}.octicon-arrow-small-left:before{content:'\f0a1'}.octicon-arrow-small-right:before{content:'\f071'}.octicon-arrow-small-up:before{content:'\f09f'}.octicon-arrow-up:before{content:'\f03d'}.octicon-beaker:before,.octicon-microscope:before{content:'\f0dd'}.octicon-bell:before{content:'\f0de'}.octicon-book:before{content:'\f007'}.octicon-bookmark:before{content:'\f07b'}.octicon-briefcase:before{content:'\f0d3'}.octicon-broadcast:before{content:'\f048'}.octicon-browser:before{content:'\f0c5'}.octicon-bug:before{content:'\f091'}.octicon-calendar:before{content:'\f068'}.octicon-check:before{content:'\f03a'}.octicon-checklist:before{content:'\f076'}.octicon-chevron-down:before{content:'\f0a3'}.octicon-chevron-left:before{content:'\f0a4'}.octicon-chevron-right:before{content:'\f078'}.octicon-chevron-up:before{content:'\f0a2'}.octicon-circle-slash:before{content:'\f084'}.octicon-circuit-board:before{content:'\f0d6'}.octicon-clippy:before{content:'\f035'}.octicon-clock:before{content:'\f046'}.octicon-cloud-download:before{content:'\f00b'}.octicon-cloud-upload:before{content:'\f00c'}.octicon-code:before{content:'\f05f'}.octicon-color-mode:before{content:'\f065'}.octicon-comment-add:before,.octicon-comment:before{content:'\f02b'}.octicon-comment-discussion:before{content:'\f04f'}.octicon-credit-card:before{content:'\f045'}.octicon-dash:before{content:'\f0ca'}.octicon-dashboard:before{content:'\f07d'}.octicon-database:before{content:'\f096'}.octicon-clone:before,.octicon-desktop-download:before{content:'\f0dc'}.octicon-device-camera:before{content:'\f056'}.octicon-device-camera-video:before{content:'\f057'}.octicon-device-desktop:before{content:'\f27c'}.octicon-device-mobile:before{content:'\f038'}.octicon-diff:before{content:'\f04d'}.octicon-diff-added:before{content:'\f06b'}.octicon-diff-ignored:before{content:'\f099'}.octicon-diff-modified:before{content:'\f06d'}.octicon-diff-removed:before{content:'\f06c'}.octicon-diff-renamed:before{content:'\f06e'}.octicon-ellipsis:before{content:'\f09a'}.octicon-eye-unwatch:before,.octicon-eye-watch:before,.octicon-eye:before{content:'\f04e'}.octicon-file-binary:before{content:'\f094'}.octicon-file-code:before{content:'\f010'}.octicon-file-directory:before{content:'\f016'}.octicon-file-media:before{content:'\f012'}.octicon-file-pdf:before{content:'\f014'}.octicon-file-submodule:before{content:'\f017'}.octicon-file-symlink-directory:before{content:'\f0b1'}.octicon-file-symlink-file:before{content:'\f0b0'}.octicon-file-text:before{content:'\f011'}.octicon-file-zip:before{content:'\f013'}.octicon-flame:before{content:'\f0d2'}.octicon-fold:before{content:'\f0cc'}.octicon-gear:before{content:'\f02f'}.octicon-gift:before{content:'\f042'}.octicon-gist:before{content:'\f00e'}.octicon-gist-secret:before{content:'\f08c'}.octicon-git-branch-create:before,.octicon-git-branch-delete:before,.octicon-git-branch:before{content:'\f020'}.octicon-git-commit:before{content:'\f01f'}.octicon-git-compare:before{content:'\f0ac'}.octicon-git-merge:before{content:'\f023'}.octicon-git-pull-request-abandoned:before,.octicon-git-pull-request:before{content:'\f009'}.octicon-globe:before{content:'\f0b6'}.octicon-graph:before{content:'\f043'}.octicon-heart:before{content:'\2665'}.octicon-history:before{content:'\f07e'}.octicon-home:before{content:'\f08d'}.octicon-horizontal-rule:before{content:'\f070'}.octicon-hubot:before{content:'\f09d'}.octicon-inbox:before{content:'\f0cf'}.octicon-info:before{content:'\f059'}.octicon-issue-closed:before{content:'\f028'}.octicon-issue-opened:before{content:'\f026'}.octicon-issue-reopened:before{content:'\f027'}.octicon-jersey:before{content:'\f019'}.octicon-key:before{content:'\f049'}.octicon-keyboard:before{content:'\f00d'}.octicon-law:before{content:'\f0d8'}.octicon-light-bulb:before{content:'\f000'}.octicon-link:before{content:'\f05c'}.octicon-link-external:before{content:'\f07f'}.octicon-list-ordered:before{content:'\f062'}.octicon-list-unordered:before{content:'\f061'}.octicon-location:before{content:'\f060'}.octicon-gLine truncated
@font-face{font-family:octicons;src:url(../fonts/octicons.eot?#iefix&v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('embedded-opentype'),url(../fonts/octicons.woff?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('woff'),url(../fonts/octicons.ttf?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d) format('truetype'),url(../fonts/octicons.svg?v=396334ee3da78f4302d25c758ae3e3ce5dc3c97d#octicons) format('svg');font-weight:400;font-style:normal}.mega-octicon,.octicon{font:normal normal normal 16px/1 octicons;display:inline-block;text-decoration:none;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mega-octicon{font-size:32px}.octicon-alert:before{content:'\f02d'}.octicon-arrow-down:before{content:'\f03f'}.octicon-arrow-left:before{content:'\f040'}.octicon-arrow-right:before{content:'\f03e'}.octicon-arrow-small-down:before{content:'\f0a0'}.octicon-arrow-small-left:before{content:'\f0a1'}.octicon-arrow-small-right:before{content:'\f071'}.octicon-arrow-small-up:before{content:'\f09f'}.octicon-arrow-up:before{content:'\f03d'}.octicon-beaker:before,.octicon-microscope:before{content:'\f0dd'}.octicon-bell:before{content:'\f0de'}.octicon-book:before{content:'\f007'}.octicon-bookmark:before{content:'\f07b'}.octicon-briefcase:before{content:'\f0d3'}.octicon-broadcast:before{content:'\f048'}.octicon-browser:before{content:'\f0c5'}.octicon-bug:before{content:'\f091'}.octicon-calendar:before{content:'\f068'}.octicon-check:before{content:'\f03a'}.octicon-checklist:before{content:'\f076'}.octicon-chevron-down:before{content:'\f0a3'}.octicon-chevron-left:before{content:'\f0a4'}.octicon-chevron-right:before{content:'\f078'}.octicon-chevron-up:before{content:'\f0a2'}.octicon-circle-slash:before{content:'\f084'}.octicon-circuit-board:before{content:'\f0d6'}.octicon-clippy:before{content:'\f035'}.octicon-clock:before{content:'\f046'}.octicon-cloud-download:before{content:'\f00b'}.octicon-cloud-upload:before{content:'\f00c'}.octicon-code:before{content:'\f05f'}.octicon-color-mode:before{content:'\f065'}.octicon-comment-add:before,.octicon-comment:before{content:'\f02b'}.octicon-comment-discussion:before{content:'\f04f'}.octicon-credit-card:before{content:'\f045'}.octicon-dash:before{content:'\f0ca'}.octicon-dashboard:before{content:'\f07d'}.octicon-database:before{content:'\f096'}.octicon-clone:before,.octicon-desktop-download:before{content:'\f0dc'}.octicon-device-camera:before{content:'\f056'}.octicon-device-camera-video:before{content:'\f057'}.octicon-device-desktop:before{content:'\f27c'}.octicon-device-mobile:before{content:'\f038'}.octicon-diff:before{content:'\f04d'}.octicon-diff-added:before{content:'\f06b'}.octicon-diff-ignored:before{content:'\f099'}.octicon-diff-modified:before{content:'\f06d'}.octicon-diff-removed:before{content:'\f06c'}.octicon-diff-renamed:before{content:'\f06e'}.octicon-ellipsis:before{content:'\f09a'}.octicon-eye-unwatch:before,.octicon-eye-watch:before,.octicon-eye:before{content:'\f04e'}.octicon-file-binary:before{content:'\f094'}.octicon-file-code:before{content:'\f010'}.octicon-file-directory:before{content:'\f016'}.octicon-file-media:before{content:'\f012'}.octicon-file-pdf:before{content:'\f014'}.octicon-file-submodule:before{content:'\f017'}.octicon-file-symlink-directory:before{content:'\f0b1'}.octicon-file-symlink-file:before{content:'\f0b0'}.octicon-file-text:before{content:'\f011'}.octicon-file-zip:before{content:'\f013'}.octicon-flame:before{content:'\f0d2'}.octicon-fold:before{content:'\f0cc'}.octicon-gear:before{content:'\f02f'}.octicon-gift:before{content:'\f042'}.octicon-gist:before{content:'\f00e'}.octicon-gist-secret:before{content:'\f08c'}.octicon-git-branch-create:before,.octicon-git-branch-delete:before,.octicon-git-branch:before{content:'\f020'}.octicon-git-commit:before{content:'\f01f'}.octicon-git-compare:before{content:'\f0ac'}.octicon-git-merge:before{content:'\f023'}.octicon-git-pull-request-abandoned:before,.octicon-git-pull-request:before{content:'\f009'}.octicon-globe:before{content:'\f0b6'}.octicon-graph:before{content:'\f043'}.octicon-heart:before{content:'\2665'}.octicon-history:before{content:'\f07e'}.octicon-home:before{content:'\f08d'}.octicon-horizontal-rule:before{content:'\f070'}.octicon-hubot:before{content:'\f09d'}.octicon-inbox:before{content:'\f0cf'}.octicon-info:before{content:'\f059'}.octicon-issue-closed:before{content:'\f028'}.octicon-issue-opened:before{content:'\f026'}.octicon-issue-reopened:before{content:'\f027'}.octicon-jersey:before{content:'\f019'}.octicon-key:before{content:'\f049'}.octicon-keyboard:before{content:'\f00d'}.octicon-law:before{content:'\f0d8'}.octicon-light-bulb:before{content:'\f000'}.octicon-link:before{content:'\f05c'}.octicon-link-external:before{content:'\f07f'}.octicon-list-ordered:before{content:'\f062'}.octicon-list-unordered:before{content:'\f061'}.octicon-location:before{content:'\f060'}.octicon-gLine truncated
+1
View File
@@ -46,6 +46,7 @@
}
}
.user.activate,
.signin,
.signup {
@input-padding: 200px!important;
+1
View File
@@ -20,5 +20,6 @@ func TemplatePreview(ctx *middleware.Context) {
ctx.Data["ActiveCodeLives"] = setting.Service.ActiveCodeLives / 60
ctx.Data["ResetPwdCodeLives"] = setting.Service.ResetPwdCodeLives / 60
ctx.Data["CurDbValue"] = ""
ctx.HTML(200, base.TplName(ctx.Params("*")))
}
+1 -1
View File
@@ -45,6 +45,7 @@ func checkRunMode() {
func NewServices() {
setting.NewServices()
mailer.NewContext()
social.NewOauthService()
}
@@ -53,7 +54,6 @@ func GlobalInit() {
setting.NewContext()
log.Trace("Custom path: %s", setting.CustomPath)
log.Trace("Log path: %s", setting.LogRootPath)
mailer.NewContext()
models.LoadConfigs()
NewServices()
+2 -2
View File
@@ -249,7 +249,7 @@ func SignUpPost(ctx *middleware.Context, cpt *captcha.Captcha, form auth.Registe
// Send confirmation e-mail, no need for social account.
if !isOauth && setting.Service.RegisterEmailConfirm && u.Id > 1 {
mailer.SendRegisterMail(ctx.Render, u)
mailer.SendActivateAccountMail(ctx.Context, u)
ctx.Data["IsSendRegisterMail"] = true
ctx.Data["Email"] = u.Email
ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60
@@ -278,7 +278,7 @@ func Activate(ctx *middleware.Context) {
ctx.Data["ResendLimited"] = true
} else {
ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60
mailer.SendActiveMail(ctx.Render, ctx.User)
mailer.SendActivateAccountMail(ctx.Context, ctx.User)
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
+1 -1
View File
@@ -225,7 +225,7 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) {
// Send confirmation e-mail
if setting.Service.RegisterEmailConfirm {
mailer.SendActivateEmail(ctx.Render, ctx.User, e)
mailer.SendActivateEmailMail(ctx.Context, ctx.User, e)
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{.User.Name}}, please activate your account</title>
</head>
<body>
<p>Hi <b>{{.User.Name}}</b>, thanks for registering at {{.AppName}}!</p>
<p>Please click the following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>:</p>
<p><a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a></p>
<p>Not working? Try copying and pasting it to your browser.</p>
<p>© 2015 <a target="_blank" href="http://gogs.io">Gogs: Go Git Service</a></p>
</body>
</html>
-33
View File
@@ -1,33 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{.User.Name}}, please activate your account</title>
</head>
<body style="background:#eee;">
<div style="color:#333; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;">
<div style="width:600px;margin:0 auto; padding:40px 0 20px;">
<div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);">
<div style="padding: 20px 15px;">
<h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><img src="{{.AppUrl}}/img/favicon.png" style="height: 32px; margin-bottom: -10px;"> <a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1>
<div style="padding:40px 15px;">
<div style="font-size:16px; padding-bottom:30px; font-weight:bold;">
Hi <span style="color: #00BFFF;">{{.User.Name}}</span>,
</div>
<div style="font-size:14px; padding:0 15px;">
<p style="margin:0;padding:0 0 9px 0;">Please click the following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>.</p>
<p style="margin:0;padding:0 0 9px 0;">
<a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a>
</p>
<p style="margin:0;padding:0 0 9px 0;">Not working? Try copying and pasting it to your browser.</p>
</div>
</div>
</div>
</div>
<div style="color:#aaa;padding:10px;text-align:center;">
© 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="http://gogits.org">Gogs: Go Git Service</a>
</div>
</div>
</div>
</body>
</html>
+16 -27
View File
@@ -1,33 +1,22 @@
<!DOCTYPE html>
<html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{.User.Name}}, welcome to {{.AppName}}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{.User.Name}}, welcome to {{.AppName}}</title>
</head>
<body style="background:#eee;">
<div style="color:#333; font:12px/1.5 Tahoma,Arial,sans-serif;; text-shadow:1px 1px #fff; padding:0; margin:0;">
<div style="width:600px;margin:0 auto; padding:40px 0 20px;">
<div style="border:1px solid #d9d9d9;border-radius:3px; background:#fff; box-shadow: 0px 2px 5px rgba(0, 0, 0,.05); -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0,.05);">
<div style="padding: 20px 15px;">
<h1 style="font-size:20px; padding:10px 0 20px; margin:0; border-bottom:1px solid #ddd;"><img src="{{.AppUrl}}/img/favicon.png" style="height: 32px; margin-bottom: -10px;"> <a style="color:#333;text-decoration:none;" target="_blank" href="{{.AppUrl}}">{{.AppName}}</a></h1>
<div style="padding:40px 15px;">
<div style="font-size:16px; padding-bottom:30px; font-weight:bold;">
Hi <span style="color: #00BFFF;">{{.User.Name}}</span>, this is your registration email for {{.AppName}}!
</div>
<div style="font-size:14px; padding:0 15px;">
<p style="margin:0;padding:0 0 9px 0;">Please click the following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>.</p>
<p style="margin:0;padding:0 0 9px 0;">
<a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a>
</p>
<p style="margin:0;padding:0 0 9px 0;">Not working? Try copying and pasting it to your browser.</p>
</div>
</div>
</div>
</div>
<div style="color:#aaa;padding:10px;text-align:center;">
© 2014 <a style="color:#888;text-decoration:none;" target="_blank" href="http://gogits.org">Gogs: Go Git Service</a>
</div>
<body class="mail register success">
<div class="ui segment">
<div class="ui header">
<img class="ui image" src="{{.AppUrl}}/img/favicon.png">
{{.AppName}}
</div>
</div>
<div class="ui divider"></div>
<p>Hi <b>{{.User.Name}}</b>, this is your registration email for {{.AppName}}!</p>
<p>Please click the following link to verify your e-mail address within <b>{{.ActiveCodeLives}} hours</b>:</p>
<p><a href="{{.AppUrl}}user/activate?code={{.Code}}">{{.AppUrl}}user/activate?code={{.Code}}</a></p>
<p>Not working? Try copying and pasting it to your browser.</p>
</div>
<p class="copyright text grey">© 2015 <a target="_blank" href="http://gogs.io">Gogs: Go Git Service</a></p>
</body>
</html>
+28 -22
View File
@@ -1,39 +1,45 @@
{{template "ng/base/head" .}}
{{template "ng/base/header" .}}
<div id="sign-wrapper">
<form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="{{AppSubUrl}}/user/activate" method="post">
{{template "base/head" .}}
<div class="user activate">
<div class="ui middle very relaxed page grid">
<div class="column">
<form class="ui form" action="{{AppSubUrl}}/user/activate" method="post">
{{.CsrfTokenHtml}}
<div class="panel-header">
<h2>{{.i18n.Tr "auth.active_your_account"}}</h2>
</div>
<div class="panel-content">
{{if .IsActivatePage}}
<h2 class="ui top attached header">
{{.i18n.Tr "auth.active_your_account"}}
</h2>
<div class="ui attached segment">
{{if .IsActivatePage}}
{{if .ServiceNotEnabled}}
<p>{{.i18n.Tr "auth.disable_register_mail"}}</p>
{{else if .ResendLimited}}
<p>{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
{{else}}
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .SignedUser.Email .Hours | Str2html}}</p>
<hr/>
<label></label>
<a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .SignedUser.Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
<div class="ui divider"></div>
<div class="text right">
<a class="ui green button" href="http://{{Mail2Domain .SignedUser.Email}}">{{.i18n.Tr "auth.sign_in_to_account"}}</a>
</div>
{{end}}
{{else}}
{{else}}
{{if .IsSendRegisterMail}}
<p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .Hours | Str2html}}</p>
<hr/>
<label></label>
<a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_to_account"}}</a>
<div class="ui divider"></div>
<div class="text right">
<a class="ui green button" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_to_account"}}</a>
</div>
{{else if .IsActivateFailed}}
<p>{{.i18n.Tr "auth.invalid_code"}}</p>
{{else}}
<p>{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
<hr/>
<label></label>
<button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.resend_mail"}}</button>
<div class="ui divider"></div>
<div class="text right">
<button class="ui blue button" href="http://{{Mail2Domain .SignedUser.Email}}">{{.i18n.Tr "auth.resend_mail"}}</button>
</div>
{{end}}
{{end}}
{{end}}
</div>
</form>
</form>
</div>
</div>
</div>
{{template "ng/base/footer" .}}
{{template "base/footer" .}}