mirror of
https://github.com/coaidev/coai.git
synced 2025-05-20 05:20:15 +09:00
feat: SMTP Compatibility Enhancement and SSL Protocol Support (#174)
This commit is contained in:
parent
9d4ff7285a
commit
6f3cdad1e7
@ -20,6 +20,7 @@ export type GeneralState = {
|
|||||||
|
|
||||||
export type MailState = {
|
export type MailState = {
|
||||||
host: string;
|
host: string;
|
||||||
|
protocol: boolean;
|
||||||
port: number;
|
port: number;
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
@ -137,6 +138,7 @@ export const initialSystemState: SystemProps = {
|
|||||||
auth_footer: false,
|
auth_footer: false,
|
||||||
},
|
},
|
||||||
mail: {
|
mail: {
|
||||||
|
protocol: false,
|
||||||
host: "",
|
host: "",
|
||||||
port: 465,
|
port: 465,
|
||||||
username: "",
|
username: "",
|
||||||
|
@ -704,6 +704,7 @@
|
|||||||
"debugMode": "调试模式",
|
"debugMode": "调试模式",
|
||||||
"debugModeTip": "调试模式,开启后日志将输出详细的请求参数等的日志,用于排查问题",
|
"debugModeTip": "调试模式,开启后日志将输出详细的请求参数等的日志,用于排查问题",
|
||||||
"mailHost": "发件域名",
|
"mailHost": "发件域名",
|
||||||
|
"mailProtocol": "发件协议",
|
||||||
"mailPort": "SMTP 端口",
|
"mailPort": "SMTP 端口",
|
||||||
"mailUser": "用户名",
|
"mailUser": "用户名",
|
||||||
"mailPass": "密码",
|
"mailPass": "密码",
|
||||||
|
@ -513,6 +513,7 @@
|
|||||||
"backend": "Backend Domain",
|
"backend": "Backend Domain",
|
||||||
"backendTip": "Backend domain name (docker installation default path is/api), used to receive callbacks and storage, etc., default is empty\nExample: {{backend}}",
|
"backendTip": "Backend domain name (docker installation default path is/api), used to receive callbacks and storage, etc., default is empty\nExample: {{backend}}",
|
||||||
"mailHost": "Mail Host",
|
"mailHost": "Mail Host",
|
||||||
|
"mailProtocol": "Mail Protocol",
|
||||||
"mailPort": "SMTP Port",
|
"mailPort": "SMTP Port",
|
||||||
"mailUser": "Username",
|
"mailUser": "Username",
|
||||||
"mailPass": "Password",
|
"mailPass": "Password",
|
||||||
|
@ -513,6 +513,7 @@
|
|||||||
"backend": "バックエンドドメイン",
|
"backend": "バックエンドドメイン",
|
||||||
"backendTip": "バックエンドドメイン名( dockerインストールのデフォルトパスは/api )、コールバックやストレージなどを受信するために使用、デフォルトは空です\n例:{{ backend}}",
|
"backendTip": "バックエンドドメイン名( dockerインストールのデフォルトパスは/api )、コールバックやストレージなどを受信するために使用、デフォルトは空です\n例:{{ backend}}",
|
||||||
"mailHost": "送信ドメイン名",
|
"mailHost": "送信ドメイン名",
|
||||||
|
"mailProtocol": "送信プロトコル",
|
||||||
"mailPort": "SMTPポート",
|
"mailPort": "SMTPポート",
|
||||||
"mailUser": "ユーザー名",
|
"mailUser": "ユーザー名",
|
||||||
"mailPass": "パスワード",
|
"mailPass": "パスワード",
|
||||||
|
@ -513,6 +513,7 @@
|
|||||||
"backend": "Домен бэкэнда",
|
"backend": "Домен бэкэнда",
|
||||||
"backendTip": "Имя домена бэкенда (путь установки докера по умолчанию -/api), используется для получения обратных вызовов и хранения и т. д., значение по умолчанию пусто\nПример: {{backend}}",
|
"backendTip": "Имя домена бэкенда (путь установки докера по умолчанию -/api), используется для получения обратных вызовов и хранения и т. д., значение по умолчанию пусто\nПример: {{backend}}",
|
||||||
"mailHost": "Почтовый хост",
|
"mailHost": "Почтовый хост",
|
||||||
|
"mailProtocol": "Протокол отправки",
|
||||||
"mailPort": "Порт SMTP",
|
"mailPort": "Порт SMTP",
|
||||||
"mailUser": "Имя пользователя",
|
"mailUser": "Имя пользователя",
|
||||||
"mailPass": "Пароль",
|
"mailPass": "Пароль",
|
||||||
|
@ -12,6 +12,13 @@ import Paragraph, {
|
|||||||
ParagraphSpace,
|
ParagraphSpace,
|
||||||
} from "@/components/Paragraph.tsx";
|
} from "@/components/Paragraph.tsx";
|
||||||
import { Button } from "@/components/ui/button.tsx";
|
import { Button } from "@/components/ui/button.tsx";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select.tsx";
|
||||||
import { Label } from "@/components/ui/label.tsx";
|
import { Label } from "@/components/ui/label.tsx";
|
||||||
import { Input } from "@/components/ui/input.tsx";
|
import { Input } from "@/components/ui/input.tsx";
|
||||||
import { useMemo, useReducer, useState } from "react";
|
import { useMemo, useReducer, useState } from "react";
|
||||||
@ -283,8 +290,8 @@ function Mail({ data, dispatch, onChange }: CompProps<MailState>) {
|
|||||||
data.username.length > 0 &&
|
data.username.length > 0 &&
|
||||||
data.password.length > 0 &&
|
data.password.length > 0 &&
|
||||||
data.from.length > 0 &&
|
data.from.length > 0 &&
|
||||||
/\w+@\w+\.\w+/.test(data.from) &&
|
data.username.includes("@") &&
|
||||||
!data.username.includes("@")
|
!/\w+@/.test(data.from)
|
||||||
);
|
);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
@ -332,6 +339,30 @@ function Mail({ data, dispatch, onChange }: CompProps<MailState>) {
|
|||||||
placeholder={`smtp.qcloudmail.com`}
|
placeholder={`smtp.qcloudmail.com`}
|
||||||
/>
|
/>
|
||||||
</ParagraphItem>
|
</ParagraphItem>
|
||||||
|
<ParagraphItem>
|
||||||
|
<Label>
|
||||||
|
<Require /> {t("admin.system.mailProtocol")}
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={data.protocol ? "true" : "false"}
|
||||||
|
onValueChange={(value: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: "update:mail.protocol",
|
||||||
|
value: value === "true",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className={`select`}>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={data.protocol ? t("admin.system.mailProtocolTLS") : t("admin.system.mailProtocolSSL")}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="true">TLS</SelectItem>
|
||||||
|
<SelectItem value="false">SSL</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</ParagraphItem>
|
||||||
<ParagraphItem>
|
<ParagraphItem>
|
||||||
<Label>
|
<Label>
|
||||||
<Require /> {t("admin.system.mailPort")}
|
<Require /> {t("admin.system.mailPort")}
|
||||||
@ -360,7 +391,7 @@ function Mail({ data, dispatch, onChange }: CompProps<MailState>) {
|
|||||||
}
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
"transition-all duration-300",
|
"transition-all duration-300",
|
||||||
data.username.includes("@") && `border-red-700`,
|
!data.username.includes("@") && `border-red-700`,
|
||||||
)}
|
)}
|
||||||
placeholder={t("admin.system.mailUser")}
|
placeholder={t("admin.system.mailUser")}
|
||||||
/>
|
/>
|
||||||
@ -396,7 +427,7 @@ function Mail({ data, dispatch, onChange }: CompProps<MailState>) {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"transition-all duration-300",
|
"transition-all duration-300",
|
||||||
data.from.length > 0 &&
|
data.from.length > 0 &&
|
||||||
!/\w+@\w+\.\w+/.test(data.from) &&
|
!/\w+@/.test(data.from) &&
|
||||||
`border-red-700`,
|
`border-red-700`,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -4,8 +4,9 @@ import (
|
|||||||
"chat/globals"
|
"chat/globals"
|
||||||
"chat/utils"
|
"chat/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiInfo struct {
|
type ApiInfo struct {
|
||||||
@ -54,6 +55,7 @@ type whiteList struct {
|
|||||||
|
|
||||||
type mailState struct {
|
type mailState struct {
|
||||||
Host string `json:"host" mapstructure:"host"`
|
Host string `json:"host" mapstructure:"host"`
|
||||||
|
Protocol bool `json:"protocol" mapstructure:"protocol"`
|
||||||
Port int `json:"port" mapstructure:"port"`
|
Port int `json:"port" mapstructure:"port"`
|
||||||
Username string `json:"username" mapstructure:"username"`
|
Username string `json:"username" mapstructure:"username"`
|
||||||
Password string `json:"password" mapstructure:"password"`
|
Password string `json:"password" mapstructure:"password"`
|
||||||
@ -162,6 +164,7 @@ func (c *SystemConfig) GetBackend() string {
|
|||||||
func (c *SystemConfig) GetMail() *utils.SmtpPoster {
|
func (c *SystemConfig) GetMail() *utils.SmtpPoster {
|
||||||
return utils.NewSmtpPoster(
|
return utils.NewSmtpPoster(
|
||||||
c.Mail.Host,
|
c.Mail.Host,
|
||||||
|
c.Mail.Protocol,
|
||||||
c.Mail.Port,
|
c.Mail.Port,
|
||||||
c.Mail.Username,
|
c.Mail.Username,
|
||||||
c.Mail.Password,
|
c.Mail.Password,
|
||||||
|
@ -3,22 +3,25 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gopkg.in/mail.v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"gopkg.in/mail.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SmtpPoster struct {
|
type SmtpPoster struct {
|
||||||
Host string
|
Host string
|
||||||
|
Protocol bool
|
||||||
Port int
|
Port int
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
From string
|
From string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSmtpPoster(host string, port int, username string, password string, from string) *SmtpPoster {
|
func NewSmtpPoster(host string, protocol bool, port int, username string, password string, from string) *SmtpPoster {
|
||||||
return &SmtpPoster{
|
return &SmtpPoster{
|
||||||
Host: host,
|
Host: host,
|
||||||
|
Protocol: protocol,
|
||||||
Port: port,
|
Port: port,
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
@ -35,14 +38,20 @@ func (s *SmtpPoster) SendMail(to string, subject string, body string) error {
|
|||||||
return fmt.Errorf("smtp not configured properly")
|
return fmt.Errorf("smtp not configured properly")
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := mail.NewDialer(s.Host, s.Port, s.From, s.Password)
|
dialer := mail.NewDialer(s.Host, s.Port, s.Username, s.Password)
|
||||||
message := mail.NewMessage()
|
message := mail.NewMessage()
|
||||||
|
|
||||||
message.SetHeader("From", fmt.Sprintf("%s <%s>", s.Username, s.From))
|
message.SetHeader("From", s.From)
|
||||||
message.SetHeader("To", to)
|
message.SetHeader("To", to)
|
||||||
message.SetHeader("Subject", subject)
|
message.SetHeader("Subject", subject)
|
||||||
message.SetBody("text/html", body)
|
message.SetBody("text/html", body)
|
||||||
|
|
||||||
|
if s.Protocol {
|
||||||
|
dialer.StartTLSPolicy = mail.MandatoryStartTLS
|
||||||
|
} else {
|
||||||
|
dialer.StartTLSPolicy = mail.NoStartTLS
|
||||||
|
}
|
||||||
|
|
||||||
// outlook STARTTLS policy adapter
|
// outlook STARTTLS policy adapter
|
||||||
if strings.Contains(s.Host, "outlook") {
|
if strings.Contains(s.Host, "outlook") {
|
||||||
dialer.StartTLSPolicy = mail.MandatoryStartTLS
|
dialer.StartTLSPolicy = mail.MandatoryStartTLS
|
||||||
|
Loading…
Reference in New Issue
Block a user