@@ -2,8 +2,6 @@ use std::error::Error;
22use std:: fmt:: { self , Display , Formatter } ;
33use std:: io;
44
5- use futures:: future:: Future ;
6- use futures_state_stream:: StateStream ;
75use tokio:: runtime:: current_thread;
86
97use tokio_imap:: client:: builder:: {
@@ -20,50 +18,72 @@ fn main() {
2018 let login = args. next ( ) . expect ( "no login provided" ) ;
2119 let password = args. next ( ) . expect ( "no password provided" ) ;
2220 let mailbox = args. next ( ) . expect ( "no mailbox provided" ) ;
23- if let Err ( cause) = imap_fetch ( & server, login, password, mailbox) {
24- eprintln ! ( "Fatal error: {}" , cause) ;
25- } ;
21+
22+ let mut rt = current_thread:: Runtime :: new ( ) . unwrap ( ) ;
23+ rt. block_on ( async move {
24+ if let Err ( cause) = imap_fetch ( & server, login, password, mailbox) . await {
25+ eprintln ! ( "Fatal error: {}" , cause) ;
26+ }
27+ } ) ;
2628}
2729
28- fn imap_fetch (
30+ async fn imap_fetch (
2931 server : & str ,
3032 login : String ,
3133 password : String ,
3234 mailbox : String ,
3335) -> Result < ( ) , ImapError > {
3436 eprintln ! ( "Will connect to {}" , server) ;
35- let fut_connect = TlsClient :: connect ( server) . map_err ( |cause| ImapError :: Connect { cause } ) ?;
36- let fut_responses = fut_connect
37- . and_then ( move |( _, tls_client) | {
38- tls_client
39- . call ( CommandBuilder :: login ( & login, & password) )
40- . collect ( )
41- } )
42- . and_then ( move |( _, tls_client) | {
43- tls_client. call ( CommandBuilder :: select ( & mailbox) ) . collect ( )
44- } )
45- . and_then ( move |( _, tls_client) | {
46- let cmd = CommandBuilder :: uid_fetch ( )
47- . all_after ( 1_u32 )
48- . attr ( Attribute :: Uid )
49- . attr ( Attribute :: Rfc822 ) ;
50- tls_client. call ( cmd. build ( ) ) . for_each ( move |response_data| {
51- process_email ( & response_data) ;
52- Ok ( ( ) )
53- } )
54- } )
55- . and_then ( move |tls_client| tls_client. call ( CommandBuilder :: close ( ) ) . collect ( ) )
56- . and_then ( |_| Ok ( ( ) ) )
57- . map_err ( |e| ImapError :: UidFetch { cause : e } ) ;
58- let res = current_thread:: block_on_all ( {
59- eprintln ! ( "Fetching messages..." ) ;
60- fut_responses
61- } ) ;
37+ let ( _, mut tls_client) = TlsClient :: connect ( server)
38+ . await
39+ . map_err ( |e| ImapError :: Connect { cause : e } ) ?;
40+
41+ let responses = tls_client
42+ . call ( CommandBuilder :: login ( & login, & password) )
43+ . try_collect ( )
44+ . await
45+ . map_err ( |e| ImapError :: Login { cause : e } ) ?;
46+
47+ match responses[ 0 ] . parsed ( ) {
48+ Response :: Capabilities ( _) => { }
49+ Response :: Done { information, .. } => {
50+ if let Some ( info) = information {
51+ eprintln ! ( "Login failed: {:?}" , info) ;
52+ }
53+ return Err ( ImapError :: Login {
54+ cause : io:: Error :: new ( io:: ErrorKind :: Other , "login failed" ) ,
55+ } ) ;
56+ }
57+ _ => unimplemented ! ( ) ,
58+ }
59+
60+ let _ = tls_client
61+ . call ( CommandBuilder :: select ( & mailbox) )
62+ . try_collect ( )
63+ . await
64+ . map_err ( |e| ImapError :: Select { cause : e } ) ?;
65+
66+ let cmd = CommandBuilder :: uid_fetch ( )
67+ . all_after ( 1_u32 )
68+ . attr ( Attribute :: Uid )
69+ . attr ( Attribute :: Rfc822 ) ;
70+ let _ = tls_client
71+ . call ( cmd. build ( ) )
72+ . try_for_each ( move |response_data| process_email ( response_data) )
73+ . await
74+ . map_err ( |e| ImapError :: UidFetch { cause : e } ) ?;
75+
76+ let _ = tls_client
77+ . call ( CommandBuilder :: close ( ) )
78+ . try_collect ( )
79+ . await
80+ . map_err ( |e| ImapError :: Close { cause : e } ) ?;
81+
6282 eprintln ! ( "Finished fetching messages" ) ;
63- res
83+ Ok ( ( ) )
6484}
6585
66- fn process_email ( response_data : & ResponseData ) {
86+ async fn process_email ( response_data : ResponseData ) -> Result < ( ) , io :: Error > {
6787 if let Response :: Fetch ( _, ref attr_vals) = * response_data. parsed ( ) {
6888 for val in attr_vals. iter ( ) {
6989 match * val {
@@ -77,6 +97,7 @@ fn process_email(response_data: &ResponseData) {
7797 }
7898 }
7999 }
100+ Ok ( ( ) )
80101}
81102
82103#[ derive( Debug ) ]
@@ -85,6 +106,7 @@ pub enum ImapError {
85106 Login { cause : io:: Error } ,
86107 Select { cause : io:: Error } ,
87108 UidFetch { cause : io:: Error } ,
109+ Close { cause : io:: Error } ,
88110}
89111
90112impl Error for ImapError {
@@ -97,7 +119,8 @@ impl Error for ImapError {
97119 ImapError :: Connect { ref cause }
98120 | ImapError :: Login { ref cause }
99121 | ImapError :: Select { ref cause }
100- | ImapError :: UidFetch { ref cause } => Some ( cause) ,
122+ | ImapError :: UidFetch { ref cause }
123+ | ImapError :: Close { ref cause } => Some ( cause) ,
101124 }
102125 }
103126}
@@ -109,6 +132,7 @@ impl Display for ImapError {
109132 ImapError :: Login { ref cause } => write ! ( f, "Login failed: {}" , cause) ,
110133 ImapError :: Select { ref cause } => write ! ( f, "Mailbox selection failed: {}" , cause) ,
111134 ImapError :: UidFetch { ref cause } => write ! ( f, "Fetching messages failed: {}" , cause) ,
135+ ImapError :: Close { ref cause } => write ! ( f, "Closing failed: {}" , cause) ,
112136 }
113137 }
114138}
0 commit comments