2019-12-04 01:04:38 +02:00
/*
* meli - jmap module .
*
* Copyright 2019 Manos Pitsidianakis
*
* This file is part of meli .
*
* meli is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* meli is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with meli . If not , see < http ://www.gnu.org/licenses/>.
* /
use super ::* ;
#[ derive(Debug) ]
pub struct JmapConnection {
2019-12-13 00:01:59 +02:00
pub session : JmapSession ,
2019-12-04 01:04:38 +02:00
pub request_no : Arc < Mutex < usize > > ,
pub client : Arc < Mutex < Client > > ,
2019-12-14 18:46:12 +02:00
pub online_status : Arc < Mutex < ( Instant , Result < ( ) > ) > > ,
2019-12-04 01:04:38 +02:00
pub server_conf : JmapServerConf ,
2019-12-04 19:42:31 +02:00
pub account_id : Arc < Mutex < String > > ,
2020-05-10 21:14:49 +03:00
pub method_call_states : Arc < Mutex < HashMap < & 'static str , String > > > ,
2019-12-04 01:04:38 +02:00
}
impl JmapConnection {
2019-12-17 14:12:41 +02:00
pub fn new (
server_conf : & JmapServerConf ,
online_status : Arc < Mutex < ( Instant , Result < ( ) > ) > > ,
) -> Result < Self > {
2019-12-04 01:04:38 +02:00
use reqwest ::header ;
let mut headers = header ::HeaderMap ::new ( ) ;
headers . insert (
header ::ACCEPT ,
header ::HeaderValue ::from_static ( " application/json " ) ,
) ;
headers . insert (
header ::CONTENT_TYPE ,
header ::HeaderValue ::from_static ( " application/json " ) ,
) ;
let client = reqwest ::blocking ::ClientBuilder ::new ( )
. danger_accept_invalid_certs ( server_conf . danger_accept_invalid_certs )
. default_headers ( headers )
. build ( ) ? ;
2019-12-13 00:36:26 +02:00
let mut jmap_session_resource_url = if server_conf . server_hostname . starts_with ( " https:// " ) {
server_conf . server_hostname . to_string ( )
} else {
format! ( " https:// {} " , & server_conf . server_hostname )
} ;
if server_conf . server_port ! = 443 {
jmap_session_resource_url . push ( ':' ) ;
2020-07-05 15:28:55 +03:00
jmap_session_resource_url . push_str ( & server_conf . server_port . to_string ( ) ) ;
2019-12-13 00:36:26 +02:00
}
jmap_session_resource_url . push_str ( " /.well-known/jmap " ) ;
2019-12-13 00:01:59 +02:00
let req = client
2019-12-13 00:36:26 +02:00
. get ( & jmap_session_resource_url )
2019-12-13 00:01:59 +02:00
. basic_auth (
& server_conf . server_username ,
Some ( & server_conf . server_password ) ,
)
. send ( ) ? ;
let res_text = req . text ( ) ? ;
2019-12-14 18:46:12 +02:00
let session : JmapSession = serde_json ::from_str ( & res_text ) . map_err ( | _ | {
2020-03-28 11:43:32 +02:00
let err = MeliError ::new ( format! ( " Could not connect to JMAP server endpoint for {} . Is your server hostname setting correct? (i.e. \" jmap.mailserver.org \" ) (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.) \n Reply from server: {} " , & server_conf . server_hostname , & res_text ) ) ;
2019-12-17 14:12:41 +02:00
* online_status . lock ( ) . unwrap ( ) = ( Instant ::now ( ) , Err ( err . clone ( ) ) ) ;
2019-12-14 18:46:12 +02:00
err
2020-03-28 11:43:32 +02:00
} ) ? ;
2019-12-13 00:01:59 +02:00
if ! session
. capabilities
. contains_key ( " urn:ietf:params:jmap:core " )
{
2019-12-17 14:12:41 +02:00
let err = MeliError ::new ( format! ( " Server {} did not return JMAP Core capability (urn:ietf:params:jmap:core). Returned capabilities were: {} " , & server_conf . server_hostname , session . capabilities . keys ( ) . map ( String ::as_str ) . collect ::< Vec < & str > > ( ) . join ( " , " ) ) ) ;
* online_status . lock ( ) . unwrap ( ) = ( Instant ::now ( ) , Err ( err . clone ( ) ) ) ;
return Err ( err ) ;
2019-12-13 00:01:59 +02:00
}
if ! session
. capabilities
. contains_key ( " urn:ietf:params:jmap:mail " )
{
2019-12-17 14:12:41 +02:00
let err = MeliError ::new ( format! ( " Server {} does not support JMAP Mail capability (urn:ietf:params:jmap:mail). Returned capabilities were: {} " , & server_conf . server_hostname , session . capabilities . keys ( ) . map ( String ::as_str ) . collect ::< Vec < & str > > ( ) . join ( " , " ) ) ) ;
* online_status . lock ( ) . unwrap ( ) = ( Instant ::now ( ) , Err ( err . clone ( ) ) ) ;
return Err ( err ) ;
2019-12-13 00:01:59 +02:00
}
2019-12-17 14:12:41 +02:00
* online_status . lock ( ) . unwrap ( ) = ( Instant ::now ( ) , Ok ( ( ) ) ) ;
2019-12-04 01:04:38 +02:00
let server_conf = server_conf . clone ( ) ;
Ok ( JmapConnection {
2019-12-13 00:01:59 +02:00
session ,
2019-12-04 01:04:38 +02:00
request_no : Arc ::new ( Mutex ::new ( 0 ) ) ,
client : Arc ::new ( Mutex ::new ( client ) ) ,
online_status ,
server_conf ,
2019-12-04 19:42:31 +02:00
account_id : Arc ::new ( Mutex ::new ( String ::new ( ) ) ) ,
2019-12-06 14:12:27 +02:00
method_call_states : Arc ::new ( Mutex ::new ( Default ::default ( ) ) ) ,
2019-12-04 01:04:38 +02:00
} )
}
2019-12-13 00:01:59 +02:00
pub fn mail_account_id ( & self ) -> & Id {
& self . session . primary_accounts [ " urn:ietf:params:jmap:mail " ]
}
2019-12-04 01:04:38 +02:00
}