mirror of
https://github.com/ghostersk/gowebmail.git
synced 2026-06-17 07:59:38 +01:00
fixed sending of email(sending email considered it as spam)
This commit is contained in:
+7
-11
@@ -446,6 +446,7 @@ func (d *DB) ListAuditLogs(page, pageSize int, eventFilter string) (*models.Audi
|
||||
}, rows.Err()
|
||||
}
|
||||
|
||||
|
||||
// ---- Email Accounts ----
|
||||
|
||||
func (d *DB) CreateAccount(a *models.EmailAccount) error {
|
||||
@@ -716,8 +717,7 @@ func (d *DB) GetFolderByPath(accountID int64, fullPath string) (*models.Folder,
|
||||
COALESCE(is_hidden,0), COALESCE(sync_enabled,1)
|
||||
FROM folders WHERE account_id=? AND full_path=?`, accountID, fullPath,
|
||||
).Scan(&f.ID, &f.AccountID, &f.Name, &f.FullPath, &f.FolderType, &f.UnreadCount, &f.TotalCount, &isHidden, &syncEnabled)
|
||||
f.IsHidden = isHidden == 1
|
||||
f.SyncEnabled = syncEnabled == 1
|
||||
f.IsHidden = isHidden == 1; f.SyncEnabled = syncEnabled == 1
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1072,12 +1072,8 @@ func (d *DB) IsRemoteContentAllowed(userID int64, sender string) (bool, error) {
|
||||
// SetFolderVisibility sets is_hidden and sync_enabled for a folder owned by the user.
|
||||
func (d *DB) SetFolderVisibility(folderID, userID int64, isHidden, syncEnabled bool) error {
|
||||
ih, se := 0, 0
|
||||
if isHidden {
|
||||
ih = 1
|
||||
}
|
||||
if syncEnabled {
|
||||
se = 1
|
||||
}
|
||||
if isHidden { ih = 1 }
|
||||
if syncEnabled { se = 1 }
|
||||
_, err := d.sql.Exec(`
|
||||
UPDATE folders SET is_hidden=?, sync_enabled=?
|
||||
WHERE id=? AND account_id IN (SELECT id FROM email_accounts WHERE user_id=?)`,
|
||||
@@ -1089,11 +1085,11 @@ func (d *DB) GetFolderByID(folderID int64) (*models.Folder, error) {
|
||||
f := &models.Folder{}
|
||||
var isHidden, syncEnabled int
|
||||
err := d.sql.QueryRow(
|
||||
`SELECT id, account_id, name, full_path, folder_type, unread_count, total_count
|
||||
`SELECT id, account_id, name, full_path, folder_type, unread_count, total_count,
|
||||
COALESCE(is_hidden,0), COALESCE(sync_enabled,1)
|
||||
FROM folders WHERE id=?`, folderID,
|
||||
).Scan(&f.ID, &f.AccountID, &f.Name, &f.FullPath, &f.FolderType, &f.UnreadCount, &f.TotalCount, &isHidden, &syncEnabled)
|
||||
f.IsHidden = isHidden == 1
|
||||
f.SyncEnabled = syncEnabled == 1
|
||||
f.IsHidden = isHidden == 1; f.SyncEnabled = syncEnabled == 1
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -639,7 +639,12 @@ func SendMessageFull(ctx context.Context, account *gomailModels.EmailAccount, re
|
||||
func buildMIMEMessage(buf *bytes.Buffer, account *gomailModels.EmailAccount, req *gomailModels.ComposeRequest) string {
|
||||
from := netmail.Address{Name: account.DisplayName, Address: account.EmailAddress}
|
||||
boundary := fmt.Sprintf("gomail_%x", time.Now().UnixNano())
|
||||
msgID := fmt.Sprintf("<%d.%s@gomail>", time.Now().UnixNano(), strings.ReplaceAll(account.EmailAddress, "@", "."))
|
||||
// Use the sender's actual domain for Message-ID so it passes spam filters
|
||||
domain := account.EmailAddress
|
||||
if at := strings.Index(domain, "@"); at >= 0 {
|
||||
domain = domain[at+1:]
|
||||
}
|
||||
msgID := fmt.Sprintf("<%d.%s@%s>", time.Now().UnixNano(), strings.ReplaceAll(account.EmailAddress, "@", "."), domain)
|
||||
|
||||
buf.WriteString("Message-ID: " + msgID + "\r\n")
|
||||
buf.WriteString("From: " + from.String() + "\r\n")
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/yourusername/gomail/config"
|
||||
@@ -240,6 +242,83 @@ func (h *APIHandler) TestConnection(w http.ResponseWriter, r *http.Request) {
|
||||
h.writeJSON(w, map[string]bool{"ok": true})
|
||||
}
|
||||
|
||||
// DetectMailSettings tries common IMAP/SMTP combinations for a domain and returns
|
||||
// the first working combination, or sensible defaults if nothing connects.
|
||||
func (h *APIHandler) DetectMailSettings(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Email == "" {
|
||||
h.writeError(w, http.StatusBadRequest, "email required")
|
||||
return
|
||||
}
|
||||
at := strings.Index(req.Email, "@")
|
||||
if at < 0 {
|
||||
h.writeError(w, http.StatusBadRequest, "invalid email")
|
||||
return
|
||||
}
|
||||
domain := req.Email[at+1:]
|
||||
|
||||
type candidate struct {
|
||||
host string
|
||||
port int
|
||||
}
|
||||
imapCandidates := []candidate{
|
||||
{"imap." + domain, 993},
|
||||
{"mail." + domain, 993},
|
||||
{"imap." + domain, 143},
|
||||
{"mail." + domain, 143},
|
||||
}
|
||||
smtpCandidates := []candidate{
|
||||
{"smtp." + domain, 587},
|
||||
{"mail." + domain, 587},
|
||||
{"smtp." + domain, 465},
|
||||
{"mail." + domain, 465},
|
||||
{"smtp." + domain, 25},
|
||||
}
|
||||
|
||||
type result struct {
|
||||
IMAPHost string `json:"imap_host"`
|
||||
IMAPPort int `json:"imap_port"`
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
SMTPPort int `json:"smtp_port"`
|
||||
Detected bool `json:"detected"`
|
||||
}
|
||||
|
||||
res := result{
|
||||
IMAPHost: "imap." + domain,
|
||||
IMAPPort: 993,
|
||||
SMTPHost: "smtp." + domain,
|
||||
SMTPPort: 587,
|
||||
}
|
||||
|
||||
// Try IMAP candidates (TCP dial only, no auth needed to detect)
|
||||
for _, c := range imapCandidates {
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", c.host, c.port), 4*time.Second)
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
res.IMAPHost = c.host
|
||||
res.IMAPPort = c.port
|
||||
res.Detected = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Try SMTP candidates
|
||||
for _, c := range smtpCandidates {
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", c.host, c.port), 4*time.Second)
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
res.SMTPHost = c.host
|
||||
res.SMTPPort = c.port
|
||||
res.Detected = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
h.writeJSON(w, res)
|
||||
}
|
||||
|
||||
func (h *APIHandler) DeleteAccount(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r)
|
||||
accountID := pathInt64(r, "id")
|
||||
|
||||
Reference in New Issue
Block a user