1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
use bytes::Bytes;
use futures::{Async, AsyncSink, Poll, StartSend};
use hostname::get_hostname;
use model::mail::*;
use service::*;
use tokio::io;
use tokio::prelude::future::FutureResult;
use tokio::prelude::*;

#[derive(Clone)]
pub struct ConsoleMail {
    name: Option<String>,
}

impl ConsoleMail {
    pub fn new(name: impl ToString) -> Self {
        Self {
            name: Some(name.to_string()),
        }
    }
    pub fn default() -> Self {
        Self { name: None }
    }
}

impl NamedService for ConsoleMail {
    fn name(&self) -> String {
        match self.name {
            None => match get_hostname() {
                None => "Samotop".into(),
                Some(name) => name,
            },
            Some(ref name) => name.clone(),
        }
    }
}

impl MailGuard for ConsoleMail {
    type Future = FutureResult<AcceptRecipientResult, io::Error>;
    fn accept(&self, request: AcceptRecipientRequest) -> Self::Future {
        println!("Accepting recipient {:?}", request);
        future::ok(AcceptRecipientResult::Accepted(request.rcpt))
    }
}

impl MailQueue for ConsoleMail {
    type Mail = MailSink;
    type MailFuture = FutureResult<Option<Self::Mail>, io::Error>;

    fn mail(&self, envelope: Envelope) -> Self::MailFuture {
        match envelope {
            Envelope {
                ref name,
                peer: Some(ref peer),
                local: Some(ref local),
                helo: Some(ref helo),
                mail: Some(ref mail),
                ref id,
                ref rcpts,
            } if rcpts.len() != 0 =>
            {
                println!(
                    "Mail from {} (helo: {}, mailid: {}) (peer: {}) for {} on {} ({} <- {})",
                    mail.from(),
                    helo.name(),
                    id,
                    peer,
                    rcpts
                        .iter()
                        .fold(String::new(), |s, r| s + format!("{}, ", r).as_ref()),
                    name,
                    local,
                    peer
                );
                future::ok(Some(MailSink { id: id.clone() }))
            }
            envelope => {
                warn!("Incomplete envelope: {:?}", envelope);
                future::ok(None)
            }
        }
    }
}

pub struct MailSink {
    id: String,
}

impl Sink for MailSink {
    type SinkItem = Bytes;
    type SinkError = io::Error;
    fn start_send(&mut self, bytes: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        println!("Mail data for {}: {:?}", self.id, bytes);
        Ok(AsyncSink::Ready)
    }
    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        Ok(Async::Ready(()))
    }
}

impl Mail for MailSink {
    fn queue(self) -> QueueResult {
        println!("Mail data finished for {}", self.id);
        QueueResult::QueuedWithId(self.id)
    }
}