--[[
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
]]--

-- This is compose.lua - a script for sending replies or new topics to lists

local JSON = require 'cjson'
local elastic = require 'lib/elastic'
local user = require 'lib/user'
local config = require 'lib/config'
local smtp = require 'socket.smtp'
local cross = require 'lib/cross'


function handle(r)
    local account = user.get(r)
    cross.contentType(r, "application/json")
    
    -- make sure the user is logged in
    if account and account.cid then
        -- parse response, up to 1MB of it. if >1MB, we're gonna pretend we never saw anything ;)
        local post = r:parsebody(1024*1024)
        
        -- check that recipient, subject and body exists
        if post.to and post.subject and post.body then
            -- validate recipient
            local to = ("<%s>"):format(post.to)
            local fp, lp = post.to:match("([^@]+)@([^@]+)")
            local domainIsOkay = false
            
            -- check that recipient is whitelisted in config.lua
            if type(config.accepted_domains) == "string" then
                if r.strcmp_match(lp, config.accepted_domains) or config.accepted_domains == "*" then
                    domainIsOkay = true
                end
            elseif type(config.accepted_domains) == "table" then
                for k, ad in pairs(config.accepted_domains) do
                    if r.strcmp_match(lp, ad) or ad == "*" then
                        domainIsOkay = true
                        break
                    end
                end
            end
            
            -- if we can send, then...
            if domainIsOkay then
                -- find user's full name
                local fname = nil
                if account.preferences then
                    fname = account.preferences.fullname
                end
                -- construct sender name+address
                local fr = ([[%s<%s>]]):format(fname or account.credentials.fullname, account.credentials.email)
                
                -- Using alt email??
                if account.credentials.altemail and post.alt then
                    for k, v in pairs(account.credentials.altemail) do
                        if v.email == post.alt then
                            fr = ([[%s<%s>]]):format(fname or account.credentials.fullname, v.email)
                            break
                        end
                    end
                end
                
                -- standard headers + headers we need ourselves for parsing in the archiver (notifications etc)
                local headers = {
                    ['Content-Type'] = 'text/plain; charset=utf-8',
                    ['X-PonyMail-Sender'] = r:sha1(account.cid),
                    ['X-PonyMail-Agent'] = "PonyMail Composer/0.2",
                    ['message-id'] = ("<pony-%s-%s@%s>"):format(r:sha1(account.cid), r:sha1(r:clock() .. os.time() .. r.useragent_ip), post.to:gsub("@", ".")),
                    to = to,
                    subject = post.subject,
                    from = fr,
                }
                
                -- set references and IRT if need be
                if post['references'] then
                    headers['references'] = post['references']
                end
                if post['in-reply-to'] then
                    headers['in-reply-to'] = post['in-reply-to']
                end
                local msgbody = post.body
                
                -- set an email footer if specified in config.lua
                if config.email_footer then
                    local subs = {
                        list = to:gsub("[<>]", ""),
                        domain = r.hostname,
                        port = r.port,
                        msgid = headers['message-id']
                    }
                    msgbody = msgbody .. "\n" .. config.email_footer:gsub("$([a-z]+)", function(a) return subs[a] or a end)
                end
                
                -- construct the smtp object
                local source = smtp.message{
                        headers = headers,
                        body = msgbody
                    }
                
                -- send email!
                local rv, er = smtp.send{
                    from = fr:gsub(".-<", "<"), -- MTAs only need the email address in MAIL FROM, cut out the name.
                    rcpt = to,
                    source = source,
                    server = config.mailserver
                }
                
                -- let the user know what happened
                r:puts(JSON.encode{
                    result = rv,
                    error = er,
                    src = headers
                })
            else
                r:puts(JSON.encode{
                    error = "Invalid recipient specified."
                })
            end
        else
            r:puts(JSON.encode{
                    error = "Invalid or missing headers",
                    headers = post
                })
        end
    else
        r:puts[[{"error": "You need to be logged in before you can send emails"}]]
    end
    return cross.OK
end

cross.start(handle)
