func procMail() { var to string for { client := <-SaveMailChan if user, _, addr_err := validateEmailData(client); addr_err != nil { // user, host, addr_err logln(1, fmt.Sprintln("mail_from didnt validate: %v", addr_err)+" client.mail_from: "+client.mail_from) // notify client that a save completed, -1 = error client.savedNotify <- -1 continue } else { to = user + "@" + gConfig["GM_PRIMARY_MAIL_HOST"] } logln(1, to) logln(1, client.data) length := len(client.data) client.subject = mimeHeaderDecode(client.subject) client.hash = md5hex(to + client.mail_from + client.subject + strconv.FormatInt(time.Now().UnixNano(), 10)) redis := &redisClient{} redis_err := redis.redisConnection() if redis_err == nil { msg := &ClientMessage{ From: client.mail_from, To: client.rcpt_to, Auth: client.auth, Data: client.data, Subject: client.subject, Username: client.username, } tmp, _ := json.Marshal(msg) _, do_err := redis.conn.Do("RPUSH", "email_queue", tmp) if do_err == nil { logln(1, "Email saved "+client.hash+" len: "+strconv.Itoa(length)) client.savedNotify <- 1 } else { logln(1, "Redis do error") client.savedNotify <- -1 } } else { logln(1, "redis connection error") client.savedNotify <- -1 } } }
func saveMail() { var to string var err error var body string var redis_err error var length int redis := &redisClient{} db := autorc.New("tcp", "", gConfig["MYSQL_HOST"], gConfig["MYSQL_USER"], gConfig["MYSQL_PASS"], gConfig["MYSQL_DB"]) db.Register("set names utf8") sql := "INSERT INTO " + gConfig["GM_MAIL_TABLE"] + " " sql += "(`date`, `to`, `from`, `subject`, `body`, `charset`, `mail`, `spam_score`, `hash`, `content_type`, `recipient`, `has_attach`, `ip_addr`)" sql += " values (NOW(), ?, ?, ?, ? , 'UTF-8' , ?, 0, ?, '', ?, 0, ?)" ins, sql_err := db.Prepare(sql) if sql_err != nil { logln(2, fmt.Sprintf("Sql statement incorrect: %s", sql_err)) } sql = "UPDATE gm2_setting SET `setting_value` = `setting_value`+1 WHERE `setting_name`='received_emails' LIMIT 1" incr, sql_err := db.Prepare(sql) if sql_err != nil { logln(2, fmt.Sprintf("Sql statement incorrect: %s", sql_err)) } // receives values from the channel repeatedly until it is closed. for { client := <-SaveMailChan if user, _, addr_err := validateEmailData(client); addr_err != nil { // user, host, addr_err logln(1, fmt.Sprintln("mail_from didnt validate: %v", addr_err)+" client.mail_from:"+client.mail_from) // notify client that a save completed, -1 = error client.savedNotify <- -1 continue } else { to = user + "@" + gConfig["GM_PRIMARY_MAIL_HOST"] } length = len(client.data) client.subject = mimeHeaderDecode(client.subject) client.hash = md5hex(to + client.mail_from + client.subject + strconv.FormatInt(time.Now().UnixNano(), 10)) // Add extra headers add_head := "" add_head += "Delivered-To: " + to + "\r\n" add_head += "Received: from " + client.helo + " (" + client.helo + " [" + client.address + "])\r\n" add_head += " by " + gConfig["GSMTP_HOST_NAME"] + " with SMTP id " + client.hash + "@" + gConfig["GSMTP_HOST_NAME"] + ";\r\n" add_head += " " + time.Now().Format(time.RFC1123Z) + "\r\n" // compress to save space client.data = compress(add_head + client.data) body = "gzencode" redis_err = redis.redisConnection() if redis_err == nil { _, do_err := redis.conn.Do("SETEX", client.hash, 3600, client.data) if do_err == nil { client.data = "" body = "redis" } } else { logln(1, fmt.Sprintf("redis: %v", redis_err)) } // bind data to cursor ins.Bind( to, client.mail_from, client.subject, body, client.data, client.hash, to, client.address) // save, discard result _, _, err = ins.Exec() if err != nil { logln(1, fmt.Sprintf("Database error, %v %v", err)) client.savedNotify <- -1 } else { logln(1, "Email saved "+client.hash+" len:"+strconv.Itoa(length)) _, _, err = incr.Exec() if err != nil { logln(1, fmt.Sprintf("Failed to incr count:", err)) } client.savedNotify <- 1 } } }