/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use crate::utils::server::TestServer; use email::cache::MessageCacheFetch; use hyper::StatusCode; use mail_parser::{DateTime, MessageParser}; use store::write::now; pub async fn test(test: &TestServer) { println!("Running calendar e-mail alarms tests..."); let account = test.account("john@example.com"); let client = account.webdav_client(); client .request_with_headers( "PUT", "/dav/cal/john%40example.com/default/its-alarming-how-charming-i-feel.ics", [("content-type", "text/calendar; charset=utf-8")], TEST_ALARM_1.replace( "$START", &DateTime::from_timestamp(now() as i64 + 5) .to_rfc3339() .replace(['-', ':'], ""), ), ) .await .with_status(StatusCode::CREATED); tokio::time::sleep(std::time::Duration::from_secs(6)).await; // Check that the alarm was sent let messages = test .server .get_cached_messages(client.account_id) .await .unwrap(); assert_eq!(messages.emails.items.len(), 2); for (idx, message) in messages.emails.items.iter().enumerate() { let contents = test .fetch_email(client.account_id, message.document_id) .await; let message = MessageParser::new().parse(&contents).unwrap(); let contents = message .html_bodies() .next() .unwrap() .text_contents() .unwrap(); if idx == 0 { // First alarm does not have a summary or description assert!( contents.contains("See the pretty girl in that mirror there"), "failed for {contents}" ); assert!( contents.contains("What mirror where?!"), "failed for {contents}" ); } else { assert!( contents.contains("I feel pretty and witty and gay"), "failed for {contents}" ); assert!( contents.contains("It's alarming how charming I feel."), "failed for {contents}" ); } assert!( contents.contains(concat!( "/dav/cal/john%40example.com/default/", "its-alarming-how-charming-i-feel.ics" )), "failed for {contents}" ); // The logo is an inline part, so the template must reference it by cid: URI let html = message.html_bodies().next().unwrap().contents().to_vec(); let html = String::from_utf8(html).unwrap(); assert!( html.contains("src=\"cid:logo."), "alarm logo must be referenced as a cid: URI: {html}" ); // A conference URI is rendered as a hyperlink assert!( html.contains("href=\"https://meet.example.com/west-side\""), "alarm must link the conference URI: {html}" ); if let Some(out_dir) = super::template_out_dir() { let path = out_dir.join(format!("alarm_template_{idx}.html")); std::fs::write(&path, &html).expect("Failed to write alarm template to file"); println!("Alarm template {idx} -> {}", path.display()); } } client.delete_default_containers().await; test.destroy_all_mailboxes(account).await; test.assert_is_empty().await } const TEST_ALARM_1: &str = r#"BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT UID: 2371c2d9-a136-43b0-bba3-f6ab249ad46e SUMMARY:See the pretty girl in that mirror there DESCRIPTION:What mirror where?! DTSTART:$START DTEND;TZID=America/New_York:21250221T180000 LOCATION:West Side CONFERENCE;VALUE=URI;FEATURE=VIDEO:https://meet.example.com/west-side BEGIN:VALARM TRIGGER:-P2S ACTION:EMAIL ATTENDEE:mailto:john_doe@unknown.com SUMMARY:I feel pretty and witty and gay DESCRIPTION:I feel charming, Oh, so charming, It's alarming how charming I feel. END:VALARM BEGIN:VALARM TRIGGER:-P4S ACTION:EMAIL END:VALARM END:VEVENT END:VCALENDAR "#;