Files
mail/onboarding.go
titor 52c5eb5ae8 feat: 重构配置文件格式并添加 IMAP ID 命令支持
- 配置文件分离:用户配置与项目配置分离,项目级配置(客户端信息、需要 ID 命令的 provider)放在代码中
- 新增 check_id 字段:用户可选择禁用单个账户的 ID 命令发送
- 简化 provider:只保留 163 和 QQ,移除未使用的 Gmail/Outlook/188 等
- 修复 163 邮箱收件箱问题:通过发送 IMAP ID 命令解决 Unsafe Login 错误

BREAKING CHANGE: 配置文件格式变化,旧配置不兼容
2026-04-10 00:39:06 +08:00

202 lines
4.0 KiB
Go

package main
import (
"fmt"
"charm.land/huh/v2"
)
var encryptionOptions = []huh.Option[string]{
huh.NewOption("STARTTLS", "starttls"),
huh.NewOption("SSL/TLS", "ssl"),
huh.NewOption("None", "none"),
}
func getEncryptionFromOption(option string) string {
switch option {
case "ssl":
return "ssl"
case "none":
return "none"
default:
return "starttls"
}
}
func runOnboarding() error {
var accountName string
var email string
var provider string
var smtpHost string
var smtpPort string
var imapHost string
var imapPort string
var smtpUsername string
var smtpPassword string
var smtpEncryption string
var smtpInsecure bool
var unsafeHTML bool
form := huh.NewForm(
huh.NewGroup(
huh.NewNote().
Title("欢迎使用 Pop").
Description("让我们先配置一下邮件账户。"),
),
huh.NewGroup(
huh.NewInput().
Title("邮箱地址").
Value(&email),
huh.NewInput().
Title("账户名称 (可选)").
Value(&accountName),
),
)
err := form.Run()
if err != nil {
return err
}
provider = getProviderName(email)
hasDefaults := false
if defaults, ok := providerDefaults[provider]; ok {
hasDefaults = true
smtpHost = defaults.SMTPHost
smtpPort = fmt.Sprintf("%d", defaults.SMTPPort)
imapHost = defaults.IMAPHost
imapPort = fmt.Sprintf("%d", defaults.IMAPPort)
smtpEncryption = defaults.SMTPEncryption
}
if !hasDefaults {
provider = "custom"
}
var form2 *huh.Form
if hasDefaults {
form2 = huh.NewForm(
huh.NewGroup(
huh.NewNote().
Title("已识别: "+provider).
Description(fmt.Sprintf("SMTP: %s:%s | IMAP: %s:%s", smtpHost, smtpPort, imapHost, imapPort)),
),
huh.NewGroup(
huh.NewConfirm().
Title("使用默认配置?").
Affirmative("是").
Negative("否, 手动配置").
Value(&hasDefaults),
),
)
} else {
form2 = huh.NewForm(
huh.NewGroup(
huh.NewNote().
Title("未知邮箱服务商").
Description("请手动配置服务器地址。"),
),
huh.NewGroup(
huh.NewInput().
Title("IMAP 服务器").
Value(&imapHost),
huh.NewInput().
Title("IMAP 端口").
Value(&imapPort),
),
huh.NewGroup(
huh.NewInput().
Title("SMTP 服务器").
Value(&smtpHost),
huh.NewInput().
Title("SMTP 端口").
Value(&smtpPort),
huh.NewSelect[string]().
Title("加密方式").
Options(encryptionOptions...).
Value(&smtpEncryption),
),
)
}
err = form2.Run()
if err != nil {
return err
}
form3 := huh.NewForm(
huh.NewGroup(
huh.NewInput().
Title("用户名").
Value(&smtpUsername),
huh.NewInput().
Title("密码/授权码").
Password(true).
Value(&smtpPassword),
),
huh.NewGroup(
huh.NewConfirm().
Title("跳过 TLS 验证?").
Affirmative("是").
Negative("否").
Value(&smtpInsecure),
),
huh.NewGroup(
huh.NewConfirm().
Title("启用 unsafe HTML?").
Affirmative("是").
Negative("否").
Value(&unsafeHTML),
),
)
err = form3.Run()
if err != nil {
return err
}
cfg := Config{
From: FromConfig{Account: accountName},
Signature: "",
UnsafeHTML: unsafeHTML,
Defaults: DefaultsConfig{Encryption: smtpEncryption},
Accounts: []Account{
{
Name: accountName,
Email: email,
Provider: provider,
Username: smtpUsername,
Password: smtpPassword,
IMAP: IMAPConfig{
Host: imapHost,
Password: smtpPassword,
},
SMTP: SMTPConfig{
Host: smtpHost,
Username: smtpUsername,
Password: smtpPassword,
InsecureSkipVerify: smtpInsecure,
},
},
},
}
if imapPort != "" {
fmt.Sscanf(imapPort, "%d", &cfg.Accounts[0].IMAP.Port)
}
if smtpPort != "" {
fmt.Sscanf(smtpPort, "%d", &cfg.Accounts[0].SMTP.Port)
}
if smtpEncryption == "" {
cfg.Accounts[0].SMTP.Encryption = "starttls"
} else {
cfg.Accounts[0].SMTP.Encryption = getEncryptionFromOption(smtpEncryption)
}
if cfg.Accounts[0].Name == "" {
cfg.Accounts[0].Name = provider
}
return saveConfig(cfg)
}