Files
mail_api_go/pkg/api/email_api.go
huangzhenpc a8d25054fc sdd
2025-05-23 23:08:02 +08:00

867 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package api
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"strings"
"time"
)
// 初始化随机数生成器
func init() {
rand.Seed(time.Now().UnixNano())
}
// Client 表示Stalwart邮件API客户端
type Client struct {
Config *Config
APIBaseURL string
}
// NewClient 创建新的API客户端
func NewClient(config *Config) *Client {
client := &Client{
Config: config,
APIBaseURL: config.API.BaseURL,
}
if config.API.DisableProxy {
DisableProxy()
}
return client
}
// AuthType 认证类型
type AuthType string
const (
// BasicAuth 表示基本认证
BasicAuth AuthType = "basic"
// APIKeyAuth 表示API Key认证
APIKeyAuth AuthType = "apikey"
)
// User 表示用户信息
type User struct {
ID int `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
Quota int64 `json:"quota"`
Emails []string `json:"emails"`
MemberOf []string `json:"memberOf"`
Roles []string `json:"roles"`
Secrets []string `json:"secrets"`
}
// UserList 表示用户列表响应
type UserList struct {
Data struct {
Items []User `json:"items"`
Total int `json:"total"`
} `json:"data"`
}
// APIResponse 表示通用API响应
type APIResponse struct {
Data json.RawMessage `json:"data"`
Error string `json:"error"`
Message string `json:"message"`
Field string `json:"field"`
Value string `json:"value"`
}
// GenerateRandomUsername 生成随机用户名
func GenerateRandomUsername(length int) string {
// 常见的英文名
firstNames := []string{
"alex", "bob", "chris", "david", "eric", "frank", "gary", "henry",
"ian", "jack", "kevin", "leo", "mike", "nick", "oliver", "peter",
"ryan", "sam", "tom", "victor", "william", "zack",
"anna", "betty", "cathy", "diana", "emma", "fiona", "grace", "helen",
"irene", "jane", "kate", "lily", "mary", "nina", "olivia", "penny",
"queen", "rose", "sarah", "tina", "uma", "vicky", "wendy", "zoe",
}
// 常见的姓氏
lastNames := []string{
"smith", "johnson", "williams", "jones", "brown", "davis", "miller",
"wilson", "taylor", "clark", "hall", "lee", "allen", "young", "king",
"wright", "hill", "scott", "green", "adams", "baker", "carter", "cook",
}
// 随机选择名和姓
firstName := firstNames[rand.Intn(len(firstNames))]
lastName := lastNames[rand.Intn(len(lastNames))]
// 添加1-999的随机数字
number := rand.Intn(999) + 1
// 组合成用户名 - 不使用特殊字符,直接连接
username := fmt.Sprintf("%s%s%d", firstName, lastName, number)
// 如果指定了长度且用户名太长,就截断
if length > 0 && len(username) > length {
username = username[:length]
}
return username
}
// GenerateRandomPassword 生成随机密码
func GenerateRandomPassword(length int) string {
if length <= 0 {
length = 10 // 默认10位密码
}
// 简单词汇列表
words := []string{
"apple", "blue", "cat", "dog", "easy", "fish", "good", "home",
"idea", "jump", "king", "love", "moon", "nice", "open", "park",
"queen", "red", "star", "time", "user", "view", "work", "year",
}
// 随机选择一个词
word := words[rand.Intn(len(words))]
// 确保词不超过长度限制的一半
if len(word) > length/2 {
word = word[:length/2]
}
// 为剩余长度生成数字和特殊字符
remainingLength := length - len(word)
numbers := "0123456789"
specials := "@#$%&*!"
var password strings.Builder
password.WriteString(word)
// 添加至少一个特殊字符
password.WriteByte(specials[rand.Intn(len(specials))])
remainingLength--
// 添加至少一个数字
password.WriteByte(numbers[rand.Intn(len(numbers))])
remainingLength--
// 填充剩余长度
for i := 0; i < remainingLength; i++ {
// 使用大小写字母、数字组合
allChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
password.WriteByte(allChars[rand.Intn(len(allChars))])
}
// 将密码字符打乱顺序
passwordBytes := []byte(password.String())
rand.Shuffle(len(passwordBytes), func(i, j int) {
passwordBytes[i], passwordBytes[j] = passwordBytes[j], passwordBytes[i]
})
return string(passwordBytes)
}
// ParseEmail 解析邮箱地址
func (c *Client) ParseEmail(email string) (string, string) {
parts := strings.Split(email, "@")
if len(parts) == 2 {
return parts[0], parts[1]
}
return email, c.Config.User.DefaultDomain
}
// PrepareUserData 准备用户数据
func (c *Client) PrepareUserData(email, description string, password string, quota int64) map[string]interface{} {
if password == "" {
// 不再使用默认密码,而是生成随机密码
password = GenerateRandomPassword(12)
}
if quota == 0 {
quota = c.Config.User.DefaultQuota
}
if description == "" {
description = fmt.Sprintf("%s account", email)
}
// 准备用户数据
return map[string]interface{}{
"type": "individual",
"name": email,
"description": description,
"quota": quota,
"emails": []string{email},
"memberOf": []string{},
"roles": []string{"user"},
"secrets": []string{password},
}
}
// GetAuthHeaders 获取认证头
func (c *Client) GetAuthHeaders(authType AuthType, username, password, apiKey string) map[string]string {
headers := map[string]string{
"Accept": "application/json",
"Content-Type": "application/json",
}
if authType == APIKeyAuth {
// API Key认证
if apiKey == "" {
apiKey = c.Config.Auth.APIKey
}
fmt.Printf("使用的API Key: %s\n", apiKey)
// 检查是否已经是完整的授权头
if strings.HasPrefix(apiKey, "Bearer ") {
headers["Authorization"] = apiKey
} else if strings.HasPrefix(apiKey, "api_") {
// 使用标准格式 api_XXX
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
fmt.Println("使用标准API Key格式: Bearer api_XXX")
} else {
// 可能是纯Token尝试直接使用
headers["Authorization"] = fmt.Sprintf("Bearer %s", apiKey)
fmt.Println("使用Token格式: Bearer XXX")
}
} else {
// 基本认证
if username == "" {
username = c.Config.Auth.Basic.AdminUsername
}
if password == "" {
password = c.Config.Auth.Basic.AdminPassword
}
auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
headers["Authorization"] = fmt.Sprintf("Basic %s", auth)
}
fmt.Println("使用的认证头:", headers["Authorization"])
return headers
}
// MakeAPIRequest 发送API请求
func (c *Client) MakeAPIRequest(method, endpoint string, data interface{}, headers map[string]string) (*http.Response, []byte, error) {
url := fmt.Sprintf("%s/%s", c.APIBaseURL, strings.TrimPrefix(endpoint, "/"))
fmt.Printf("发送请求: %s %s\n", method, url)
if headers["Authorization"] != "" {
authType := strings.Split(headers["Authorization"], " ")[0]
fmt.Printf("认证方式: %s\n", authType)
}
var reqBody []byte
var err error
if data != nil {
reqBody, err = json.Marshal(data)
if err != nil {
return nil, nil, fmt.Errorf("序列化请求数据失败: %w", err)
}
fmt.Printf("请求数据: %s\n", string(reqBody))
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(reqBody))
if err != nil {
return nil, nil, fmt.Errorf("创建HTTP请求失败: %w", err)
}
// 设置请求头
for key, value := range headers {
req.Header.Set(key, value)
}
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("发送HTTP请求失败: %w", err)
}
// 读取响应
respBody, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
return resp, nil, fmt.Errorf("读取响应失败: %w", err)
}
fmt.Printf("响应状态码: %d\n", resp.StatusCode)
fmt.Printf("响应内容: %s\n", string(respBody))
// 检查认证错误
if resp.StatusCode == 401 || resp.StatusCode == 403 {
fmt.Println("认证失败,可能需要尝试其他认证方式")
}
return resp, respBody, nil
}
// CreateUser 创建邮箱用户
func (c *Client) CreateUser(email, password, description string, quota int64, authType AuthType, username, authPassword, apiKey string) (int, map[string]interface{}, error) {
// 准备用户数据
userData := c.PrepareUserData(email, description, password, quota)
fmt.Printf("创建用户 %s 并设置密码...\n", email)
// 获取认证头
headers := c.GetAuthHeaders(authType, username, authPassword, apiKey)
// 创建用户
resp, respBody, err := c.MakeAPIRequest("POST", "/principal", userData, headers)
if err != nil {
return 0, nil, fmt.Errorf("创建用户请求失败: %w", err)
}
if resp == nil {
return 0, nil, fmt.Errorf("创建用户失败:未收到响应")
}
// 解析响应
var apiResp APIResponse
if err := json.Unmarshal(respBody, &apiResp); err != nil {
return 0, nil, fmt.Errorf("解析响应失败: %w", err)
}
// 检查是否返回错误
if apiResp.Error != "" {
// 特殊处理如果用户已存在可以尝试获取已存在用户的ID
if apiResp.Error == "fieldAlreadyExists" && apiResp.Field == "name" {
existingName := apiResp.Value
fmt.Printf("用户 %s 已存在,尝试获取现有用户信息...\n", existingName)
// 构造一个模拟信息
userInfo := map[string]interface{}{
"name": email,
"emails": []string{email},
"description": description,
"quota": quota,
"_note": "This user already exists",
}
// 返回一个特殊标记的ID负数表示这是一个已存在的用户
return -1, userInfo, nil
}
return 0, nil, fmt.Errorf("创建用户失败: %s - %s", apiResp.Error, apiResp.Message)
}
// 获取用户ID
var userID int
if err := json.Unmarshal(apiResp.Data, &userID); err != nil {
// 尝试解析为对象
var objData map[string]interface{}
if err := json.Unmarshal(apiResp.Data, &objData); err != nil {
return 0, nil, fmt.Errorf("解析用户ID失败: %w", err)
}
// 检查是否有id字段
if id, ok := objData["id"].(float64); ok {
userID = int(id)
} else {
return 0, nil, fmt.Errorf("未能从响应中获取用户ID")
}
}
if userID == 0 {
return 0, nil, fmt.Errorf("创建用户失败未获取到用户ID")
}
fmt.Printf("用户创建成功ID: %d\n", userID)
// 尝试获取用户详情进行验证
userInfo, err := c.GetUserDetails(userID, authType, username, authPassword, apiKey)
if err != nil || userInfo == nil {
fmt.Println("获取用户详情失败,但用户创建成功")
// 创建一个包含基本信息的对象
userInfo = map[string]interface{}{
"name": email,
"emails": []string{email},
"description": description,
"quota": quota,
"_note": "This is a synthetic record as actual details could not be retrieved",
}
}
return userID, userInfo, nil
}
// GetUserDetails 获取用户详情
func (c *Client) GetUserDetails(userID int, authType AuthType, username, authPassword, apiKey string) (map[string]interface{}, error) {
fmt.Println("\n获取用户详情...")
// 获取认证头
headers := c.GetAuthHeaders(authType, username, authPassword, apiKey)
// 获取用户详情
endpoint := fmt.Sprintf("/principal/%d", userID)
resp, respBody, err := c.MakeAPIRequest("GET", endpoint, nil, headers)
if err != nil {
return nil, fmt.Errorf("获取用户详情请求失败: %w", err)
}
if resp == nil || resp.StatusCode != 200 {
return nil, fmt.Errorf("获取用户详情失败")
}
// 解析响应
var apiResp APIResponse
if err := json.Unmarshal(respBody, &apiResp); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
// 检查是否返回错误
if apiResp.Error != "" {
return nil, fmt.Errorf("获取用户详情失败: %s - %s", apiResp.Error, apiResp.Message)
}
// 解析用户数据
var userData map[string]interface{}
if err := json.Unmarshal(apiResp.Data, &userData); err != nil {
// 如果无法解析为对象,直接返回整个响应
var rawResp map[string]interface{}
if err := json.Unmarshal(respBody, &rawResp); err != nil {
return nil, fmt.Errorf("解析用户数据失败: %w", err)
}
return rawResp, nil
}
if userData == nil {
return nil, fmt.Errorf("获取用户详情失败:响应中没有用户数据")
}
// 打印关键信息
fmt.Printf("用户名: %v\n", userData["name"])
emails, _ := userData["emails"].([]interface{})
if len(emails) > 0 {
fmt.Printf("邮箱: %v\n", emails[0])
}
return userData, nil
}
// ListUsers 获取用户列表
func (c *Client) ListUsers(authType AuthType, username, authPassword, apiKey string, limit, page int) (*UserList, error) {
fmt.Println("获取用户列表...")
// 获取认证头
headers := c.GetAuthHeaders(authType, username, authPassword, apiKey)
// 构建查询参数
endpoint := fmt.Sprintf("/principal?limit=%d&page=%d", limit, page)
// 尝试不同的API端点路径
endpoints := []string{
endpoint, // 根据规范文档的主要端点
"/principals", // 原始尝试
"/users", // 通用users格式
"/user", // 单数形式
"/accounts", // 有些系统用accounts
"/directory", // 目录形式
}
var resp *http.Response
var respBody []byte
var err error
var success bool
for _, ep := range endpoints {
fmt.Printf("尝试端点: %s\n", ep)
resp, respBody, err = c.MakeAPIRequest("GET", ep, nil, headers)
if err == nil && resp != nil && resp.StatusCode == 200 {
fmt.Printf("成功的端点: %s\n", ep)
success = true
break
}
}
if !success {
return nil, fmt.Errorf("获取用户列表失败,尝试了所有可能的端点")
}
// 解析响应
fmt.Println("响应数据结构:")
fmt.Println(string(respBody))
var userList UserList
if err := json.Unmarshal(respBody, &userList); err != nil {
// 尝试解析为不同格式
var rawResp map[string]interface{}
if err := json.Unmarshal(respBody, &rawResp); err != nil {
return nil, fmt.Errorf("解析用户列表失败: %w", err)
}
// 尝试不同的数据格式
users := []User{}
// 检查data.items格式
if data, ok := rawResp["data"].(map[string]interface{}); ok {
if items, ok := data["items"].([]interface{}); ok {
for _, item := range items {
if user, ok := item.(map[string]interface{}); ok {
userObj := parseUserObject(user)
users = append(users, userObj)
}
}
userList.Data.Items = users
userList.Data.Total = len(users)
return &userList, nil
}
}
// 检查data数组格式
if data, ok := rawResp["data"].([]interface{}); ok {
for _, item := range data {
if user, ok := item.(map[string]interface{}); ok {
userObj := parseUserObject(user)
users = append(users, userObj)
}
}
userList.Data.Items = users
userList.Data.Total = len(users)
return &userList, nil
}
// 检查principals数组格式
if principals, ok := rawResp["principals"].([]interface{}); ok {
for _, item := range principals {
if user, ok := item.(map[string]interface{}); ok {
userObj := parseUserObject(user)
users = append(users, userObj)
}
}
userList.Data.Items = users
userList.Data.Total = len(users)
return &userList, nil
}
// 检查users数组格式
if usersArray, ok := rawResp["users"].([]interface{}); ok {
for _, item := range usersArray {
if user, ok := item.(map[string]interface{}); ok {
userObj := parseUserObject(user)
users = append(users, userObj)
}
}
userList.Data.Items = users
userList.Data.Total = len(users)
return &userList, nil
}
return nil, fmt.Errorf("未能从响应中提取用户列表")
}
fmt.Printf("找到 %d 个用户\n", len(userList.Data.Items))
return &userList, nil
}
// parseUserObject 解析用户对象
func parseUserObject(user map[string]interface{}) User {
userObj := User{}
// ID
if id, ok := user["id"].(float64); ok {
userObj.ID = int(id)
}
// Type
if typ, ok := user["type"].(string); ok {
userObj.Type = typ
}
// Name
if name, ok := user["name"].(string); ok {
userObj.Name = name
}
// Description
if desc, ok := user["description"].(string); ok {
userObj.Description = desc
}
// Quota
if quota, ok := user["quota"].(float64); ok {
userObj.Quota = int64(quota)
}
// Emails
if emails, ok := user["emails"].([]interface{}); ok {
for _, email := range emails {
if e, ok := email.(string); ok {
userObj.Emails = append(userObj.Emails, e)
}
}
} else if email, ok := user["emails"].(string); ok {
userObj.Emails = []string{email}
}
// MemberOf
if memberOf, ok := user["memberOf"].([]interface{}); ok {
for _, member := range memberOf {
if m, ok := member.(string); ok {
userObj.MemberOf = append(userObj.MemberOf, m)
}
}
}
// Roles
if roles, ok := user["roles"].([]interface{}); ok {
for _, role := range roles {
if r, ok := role.(string); ok {
userObj.Roles = append(userObj.Roles, r)
}
}
}
return userObj
}
// GetUserByEmail 通过邮箱地址查询用户信息
func (c *Client) GetUserByEmail(email string, authType AuthType, username, authPassword, apiKey string) (map[string]interface{}, error) {
fmt.Printf("通过邮箱查询用户: %s\n", email)
// 获取所有用户,然后过滤
userList, err := c.ListUsers(authType, username, authPassword, apiKey, 1000, 1)
if err != nil {
return nil, err
}
// 尝试在列表中查找匹配的邮箱
for _, user := range userList.Data.Items {
// 检查用户邮箱是否匹配
for _, userEmail := range user.Emails {
if userEmail == email {
fmt.Printf("找到匹配的用户ID: %d\n", user.ID)
// 获取详细信息
return c.GetUserDetails(user.ID, authType, username, authPassword, apiKey)
}
}
if user.Name == email {
fmt.Printf("找到匹配的用户ID: %d\n", user.ID)
// 获取详细信息
return c.GetUserDetails(user.ID, authType, username, authPassword, apiKey)
}
}
fmt.Printf("未找到邮箱为 %s 的用户\n", email)
return nil, fmt.Errorf("未找到用户")
}
// FormatUserList 格式化输出用户列表
func FormatUserList(userList *UserList) {
if userList == nil || len(userList.Data.Items) == 0 {
fmt.Println("没有用户数据可显示")
return
}
fmt.Println("\n=== 用户列表 ===")
fmt.Printf("找到 %d 个用户\n", len(userList.Data.Items))
fmt.Println(strings.Repeat("-", 60))
fmt.Printf("%-10s %-30s %-15s %-30s\n", "ID", "名称", "类型", "邮箱")
fmt.Println(strings.Repeat("-", 60))
for _, user := range userList.Data.Items {
email := "N/A"
if len(user.Emails) > 0 {
email = user.Emails[0]
}
// 截断过长的字符串
name := user.Name
if len(name) > 28 {
name = name[:28]
}
if len(email) > 28 {
email = email[:28]
}
fmt.Printf("%-10d %-30s %-15s %-30s\n", user.ID, name, user.Type, email)
}
fmt.Println(strings.Repeat("-", 60))
}
// FormatUserDetails 格式化输出单个用户的详细信息
func FormatUserDetails(userInfo map[string]interface{}) {
if userInfo == nil {
fmt.Println("没有用户数据可显示")
return
}
fmt.Println("\n=== 用户详细信息 ===")
fmt.Println(strings.Repeat("-", 60))
// 获取基本信息
id, _ := userInfo["id"]
name, _ := userInfo["name"]
description, _ := userInfo["description"]
typ, _ := userInfo["type"]
quota, _ := userInfo["quota"]
// 显示类型转换
var quotaFloat float64
switch q := quota.(type) {
case float64:
quotaFloat = q
case int64:
quotaFloat = float64(q)
case int:
quotaFloat = float64(q)
}
quotaMB := quotaFloat / (1024 * 1024)
fmt.Printf("ID: %v\n", id)
fmt.Printf("名称: %v\n", name)
fmt.Printf("描述: %v\n", description)
fmt.Printf("类型: %v\n", typ)
fmt.Printf("配额: %.2f MB (%.0f 字节)\n", quotaMB, quotaFloat)
// 获取邮箱
if emails, ok := userInfo["emails"].([]interface{}); ok && len(emails) > 0 {
fmt.Println("\n邮箱地址:")
for _, email := range emails {
fmt.Printf(" - %v\n", email)
}
} else if email, ok := userInfo["emails"].(string); ok {
fmt.Println("\n邮箱地址:")
fmt.Printf(" - %s\n", email)
}
// 获取成员组
if memberOf, ok := userInfo["memberOf"].([]interface{}); ok && len(memberOf) > 0 {
fmt.Println("\n所属组:")
for _, group := range memberOf {
fmt.Printf(" - %v\n", group)
}
}
// 其他属性
fmt.Println("\n其他属性:")
for key, value := range userInfo {
if key != "id" && key != "name" && key != "description" && key != "type" && key != "quota" && key != "emails" && key != "memberOf" {
// 跳过密码相关字段
if strings.Contains(strings.ToLower(key), "secret") || strings.Contains(strings.ToLower(key), "password") {
continue
}
fmt.Printf(" - %s: %v\n", key, value)
}
}
fmt.Println(strings.Repeat("-", 60))
}
// CreateEmailUser 创建邮箱用户的统一入口
func (c *Client) CreateEmailUser(emailAddress, password, description string, quota int64, authType AuthType, username, authPassword, apiKey string) (int, string, string, string, error) {
// 如果没有提供邮箱地址,则生成随机用户名
if emailAddress == "" {
randomUsername := GenerateRandomUsername(8)
// 确保用户名只包含字母和数字
for i := 0; i < len(randomUsername); i++ {
if !((randomUsername[i] >= 'a' && randomUsername[i] <= 'z') ||
(randomUsername[i] >= '0' && randomUsername[i] <= '9')) {
// 替换为字母
randomUsername = randomUsername[:i] + "x" + randomUsername[i+1:]
}
}
emailAddress = fmt.Sprintf("%s@%s", randomUsername, c.Config.User.DefaultDomain)
}
// 解析邮箱地址
usernameLocal, domain := c.ParseEmail(emailAddress)
// 确保用户名只包含字母和数字
cleanUsername := ""
for i := 0; i < len(usernameLocal); i++ {
if (usernameLocal[i] >= 'a' && usernameLocal[i] <= 'z') ||
(usernameLocal[i] >= '0' && usernameLocal[i] <= '9') {
cleanUsername += string(usernameLocal[i])
} else {
cleanUsername += "x" // 替换非法字符为x
}
}
usernameLocal = cleanUsername
email := fmt.Sprintf("%s@%s", usernameLocal, domain)
// 如果没有提供密码,生成随机密码
if password == "" {
password = GenerateRandomPassword(12)
fmt.Println("已生成随机密码")
}
// 设置认证类型消息
if authType == APIKeyAuth {
// 从API Key中提取用户名用于显示
if apiKey != "" && strings.HasPrefix(apiKey, "api_") {
decoded, err := base64.StdEncoding.DecodeString(apiKey[4:])
if err == nil {
decodedStr := string(decoded)
if strings.Contains(decodedStr, ":") {
parts := strings.SplitN(decodedStr, ":", 2)
fmt.Printf("使用API Key认证 (用户: %s)\n", parts[0])
} else {
fmt.Println("使用API Key认证")
}
} else {
fmt.Println("使用API Key认证")
}
} else {
fmt.Println("使用API Key认证")
}
} else {
actualUsername := username
if actualUsername == "" {
actualUsername = c.Config.Auth.Basic.AdminUsername
}
fmt.Printf("使用基本认证 (用户: %s)\n", actualUsername)
}
// 创建用户
userID, _, err := c.CreateUser(email, password, description, quota, authType, username, authPassword, apiKey)
if err != nil {
return 0, "", "", "", err
}
// 特殊处理如果用户已存在用户ID为负数
if userID < 0 {
fmt.Printf("用户 %s 已存在,使用现有用户信息\n", email)
userID = -userID // 转为正数便于显示
}
// 返回用户信息
return userID, usernameLocal, email, password, nil
}
// PrintUserResult 打印用户创建结果
func PrintUserResult(userID int, username, email, password string) bool {
if userID == 0 {
fmt.Println("\n创建用户失败")
return false
}
domainParts := strings.Split(email, "@")
domain := ""
if len(domainParts) > 1 {
domain = domainParts[1]
}
fmt.Println("\n=== 新创建的用户信息 ===")
fmt.Printf("用户ID: %d\n", userID)
fmt.Printf("登录名: %s\n", username)
fmt.Printf("邮箱地址: %s\n", email)
fmt.Printf("密码: %s\n", password)
fmt.Printf("\n登录信息:\n")
fmt.Printf(" - 登录名: %s\n", username)
fmt.Printf(" - 密码: %s\n", password)
fmt.Printf(" - 邮箱服务器: mail.%s\n", domain)
return true
}