The current Client::rustls() method uses rustls-platform-verifier which enforces strict certificate verification, causing failures with self-signed certificates (e.g., ProtonMail Bridge).
Error: failed to verify TLS certificate: invalid peer certificate: Other(OtherError(CaUsedAsEndEntity))
Cause
The issue is in src/client/tokio.rs in the upgrade_rustls() method:
let mut config = ClientConfig::with_platform_verifier();
rustls-platform-verifier is designed for security and intentionally doesn't provide bypass options. To ignore certificate verification, we need to use core rustls with a custom ServerCertVerifier.
Current vs. Needed Flow
Current: imap-client → rustls-platform-verifier → OS certificate store → REJECT self-signed
Needed: imap-client → custom rustls config → DangerousNoCertificateVerifier → ACCEPT all
Proposed Solution
Add an alternative method that bypasses rustls-platform-verifier entirely:
pub async fn rustls_dangerous(host: &str, port: u16, starttls: bool) -> Result<Self, ClientError>
// Implementation replaces platform verifier with custom verifier
async fn upgrade_rustls_dangerous(mut self, starttls: bool) -> Result<Self, ClientError> {
let config = ClientConfig::builder()
.with_safe_defaults()
.with_custom_certificate_verifier(Arc::new(DangerousNoCertificateVerification))
.with_no_client_auth();
config.alpn_protocols = vec![b"imap".to_vec()];
// ... rest of TLS setup unchanged
}
struct DangerousNoCertificateVerification;
impl ServerCertVerifier for DangerousNoCertificateVerification {
fn verify_server_cert(
&self,
_end_entity: &Certificate,
_intermediates: &[Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: SystemTime,
) -> Result<ServerCertVerified, Error> {
Ok(ServerCertVerified::assertion())
}
}
Related Issues
This is needed for trusted local servers like ProtonMail Bridge that use self-signed certificates where the user explicitly accepts the security risk.
Note: I'm not a Rust developer - this analysis came from working with Claude Sonnet via the CLI to figure out how to bypass verification for self-signed certificates. If I had the time I would compile and verify this, but don't have the chance right now. Hopefully it's useful and not just noise.
The current
Client::rustls()method usesrustls-platform-verifierwhich enforces strict certificate verification, causing failures with self-signed certificates (e.g., ProtonMail Bridge).Error:
failed to verify TLS certificate: invalid peer certificate: Other(OtherError(CaUsedAsEndEntity))Cause
The issue is in
src/client/tokio.rsin theupgrade_rustls()method:rustls-platform-verifier is designed for security and intentionally doesn't provide bypass options. To ignore certificate verification, we need to use core rustls with a custom ServerCertVerifier.
Current vs. Needed Flow
Current: imap-client → rustls-platform-verifier → OS certificate store → REJECT self-signed
Needed: imap-client → custom rustls config → DangerousNoCertificateVerifier → ACCEPT all
Proposed Solution
Add an alternative method that bypasses rustls-platform-verifier entirely:
Related Issues
This is needed for trusted local servers like ProtonMail Bridge that use self-signed certificates where the user explicitly accepts the security risk.
Note: I'm not a Rust developer - this analysis came from working with Claude Sonnet via the CLI to figure out how to bypass verification for self-signed certificates. If I had the time I would compile and verify this, but don't have the chance right now. Hopefully it's useful and not just noise.