From e180a1fa15e3b918c54b02bc95a2924b746f55e6 Mon Sep 17 00:00:00 2001
From: Arjan Koopen
Date: Wed, 6 May 2026 23:50:27 +0200
Subject: [PATCH 1/3] Add parser for Vodafone
---
circuit_maintenance_parser/__init__.py | 2 +
.../parsers/vodafone.py | 116 +++++
circuit_maintenance_parser/provider.py | 12 +
tests/unit/data/vodafone/vodafone1.eml | 383 ++++++++++++++++
.../unit/data/vodafone/vodafone1_result.json | 16 +
.../vodafone/vodafone1_result_combined.json | 21 +
tests/unit/data/vodafone/vodafone2.eml | 390 +++++++++++++++++
.../unit/data/vodafone/vodafone2_result.json | 16 +
.../vodafone/vodafone2_result_combined.json | 21 +
tests/unit/data/vodafone/vodafone3.eml | 411 ++++++++++++++++++
.../unit/data/vodafone/vodafone3_result.json | 16 +
.../vodafone/vodafone3_result_combined.json | 21 +
tests/unit/test_e2e.py | 17 +
tests/unit/test_parsers.py | 17 +
14 files changed, 1459 insertions(+)
create mode 100644 circuit_maintenance_parser/parsers/vodafone.py
create mode 100644 tests/unit/data/vodafone/vodafone1.eml
create mode 100644 tests/unit/data/vodafone/vodafone1_result.json
create mode 100644 tests/unit/data/vodafone/vodafone1_result_combined.json
create mode 100644 tests/unit/data/vodafone/vodafone2.eml
create mode 100644 tests/unit/data/vodafone/vodafone2_result.json
create mode 100644 tests/unit/data/vodafone/vodafone2_result_combined.json
create mode 100644 tests/unit/data/vodafone/vodafone3.eml
create mode 100644 tests/unit/data/vodafone/vodafone3_result.json
create mode 100644 tests/unit/data/vodafone/vodafone3_result_combined.json
diff --git a/circuit_maintenance_parser/__init__.py b/circuit_maintenance_parser/__init__.py
index bc994864..d1a81e20 100644
--- a/circuit_maintenance_parser/__init__.py
+++ b/circuit_maintenance_parser/__init__.py
@@ -37,6 +37,7 @@
Telstra,
Turkcell,
Verizon,
+ Vodafone,
Windstream,
Zayo,
)
@@ -72,6 +73,7 @@
Telstra,
Turkcell,
Verizon,
+ Vodafone,
Windstream,
Zayo,
)
diff --git a/circuit_maintenance_parser/parsers/vodafone.py b/circuit_maintenance_parser/parsers/vodafone.py
new file mode 100644
index 00000000..f3959f12
--- /dev/null
+++ b/circuit_maintenance_parser/parsers/vodafone.py
@@ -0,0 +1,116 @@
+"""Vodafone parser."""
+
+import logging
+import re
+from typing import Dict, List
+
+from bs4.element import ResultSet # type: ignore
+from dateutil import parser
+
+from circuit_maintenance_parser.parser import Html, Impact, Status
+
+logger = logging.getLogger(__name__)
+
+
+class HtmlParserVodafone1(Html):
+ """Notifications Parser for Vodafone notifications."""
+
+ def parse_html(self, soup: ResultSet) -> List[Dict]:
+ """Execute parsing."""
+ data: Dict[str] = {"circuits": []}
+ self.parse_crq(soup, data)
+ self.parse_tables(soup.find_all("table"), data)
+ self.parse_bold(soup.find_all("b"), data)
+
+ return [data]
+
+ def parse_tables(self, tables: ResultSet, data: Dict):
+ """Parse table element to find circuit ID's and account."""
+ for table in tables:
+ col_mapping = {}
+ for tr_elem in table.find_all("tr"):
+ col = 0
+ cid = 0
+ impact = 0
+ # look for table header
+ for th_elem in tr_elem.find_all("th"):
+ # Map column headers to column number
+ if th_elem.text.strip() != "":
+ col_mapping[th_elem.text.strip()] = col
+ col += 1
+
+ # look for regular columns
+ for td_elem in tr_elem.find_all("td"):
+ if "Customer" in col_mapping and col == col_mapping["Customer"]:
+ data["account"] = td_elem.text.strip()
+ elif "Services Affected" in col_mapping and col == col_mapping["Services Affected"]:
+ cid = td_elem.text.strip()
+ elif "Service Impact" in col_mapping and col == col_mapping["Service Impact"]:
+ # not sure if other impact types exist, can be expanded of need-be
+ if "loss of service" in td_elem.text.lower():
+ impact = Impact("OUTAGE")
+ else:
+ impact = Impact("OUTAGE")
+ col += 1
+
+ # at the end of the table row, add circuits to list, if defined
+ if cid != 0 and impact != 0:
+ data["circuits"].append({"circuit_id": cid, "impact": impact})
+
+ def parse_bold(self, bolds: ResultSet, data: Dict):
+ """Parse B (bold) elements to find summary and start+end date/time.
+
+ Example:
+ New Scheduled Start/End Date & Outage Window:
+ 06/04/2026 00:00 to 13/04/2026 00:00 UTC
+ """
+ window = 0
+ for bold in bolds:
+ # find start/end date/time
+ if (
+ data["status"] == Status("RE-SCHEDULED") and "new scheduled start" in bold.text.lower()
+ ) or "scheduled start" in bold.text.lower():
+ window_next = bold.next_sibling
+ while window_next:
+ text = window_next.text.strip()
+ if text != "":
+ window = text
+ break
+ window_next = window_next.next_sibling
+ # find summary
+ elif "description" in bold.text.lower():
+ description_next = bold.next_sibling
+ while description_next:
+ text = description_next.text.strip()
+ if text != "":
+ data["summary"] = text
+ break
+ description_next = description_next.next_sibling
+
+ if window != 0:
+ start_str, end_str = window.replace(" UTC", "").split(" to ")
+ data["start"] = self.dt2ts(parser.parse(start_str, dayfirst=True))
+ data["end"] = self.dt2ts(parser.parse(end_str, dayfirst=True))
+
+ def parse_crq(self, soup: ResultSet, data: Dict):
+ """Vodafone maintenance_id's are in the format of CRQ[0-9] with 12 digits.
+
+ Before mentioning the CRQ, the status of the maintenance can be derived, for example:
+
+ Please be advised that the Planned Works have been Completed: CRQ000001312927
+ """
+ text = soup.get_text(separator=" ")
+ match = re.search(r"\b(.*)[\s:]+(CRQ\d{12})\b", text)
+ if match:
+ data["maintenance_id"] = match.group(2)
+
+ # derive status
+ if "postponed" in match.group(1).lower():
+ data["status"] = Status("CANCELLED")
+ elif "completed" in match.group(1).lower():
+ data["status"] = Status("COMPLETED")
+ elif "rescheduled" in match.group(1).lower():
+ data["status"] = Status("RE-SCHEDULED")
+ # default status
+ else:
+ data["status"] = Status("CONFIRMED")
diff --git a/circuit_maintenance_parser/provider.py b/circuit_maintenance_parser/provider.py
index 5b02c2b0..3975571c 100644
--- a/circuit_maintenance_parser/provider.py
+++ b/circuit_maintenance_parser/provider.py
@@ -44,6 +44,7 @@
from circuit_maintenance_parser.parsers.telstra import HtmlParserTelstra1, HtmlParserTelstra2
from circuit_maintenance_parser.parsers.turkcell import HtmlParserTurkcell1
from circuit_maintenance_parser.parsers.verizon import HtmlParserVerizon1
+from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1
from circuit_maintenance_parser.parsers.windstream import HtmlParserWindstream1
from circuit_maintenance_parser.parsers.zayo import HtmlParserZayo1, SubjectParserZayo1
from circuit_maintenance_parser.processor import CombinedProcessor, GenericProcessor, SimpleProcessor
@@ -565,6 +566,17 @@ class Verizon(GenericProvider):
_default_organizer = PrivateAttr("NO-REPLY-sched-maint@EMEA.verizonbusiness.com")
+class Vodafone(GenericProvider):
+ """Vodafone provider custom class."""
+
+ _processors: List[GenericProcessor] = PrivateAttr(
+ [
+ CombinedProcessor(data_parsers=[EmailDateParser, HtmlParserVodafone1]),
+ ]
+ )
+ _default_organizer = PrivateAttr("networkchangemanagement@vodafone.com")
+
+
class Windstream(GenericProvider):
"""Windstream provider custom class."""
diff --git a/tests/unit/data/vodafone/vodafone1.eml b/tests/unit/data/vodafone/vodafone1.eml
new file mode 100644
index 00000000..8161d112
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone1.eml
@@ -0,0 +1,383 @@
+Received: from CH3PR17MB6961.namprd17.prod.outlook.com (2603:10b6:610:15a::10)
+ by CH3PR17MB6987.namprd17.prod.outlook.com with HTTPS; Thu, 30 Apr 2026
+ 13:44:26 +0000
+ARC-Seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass;
+ b=WcJu60upBjOqz5t5w3K1qOYsgLOpH8pTXLRFVdxQyE6bAuUldZ0OYbeAzdAY8f+MVItlAiBY8RNCygwlLfFTVvF9NF2oPmB5+Bi58OpTjJhzafOck8LeGfn6FfeSrIIqR5T48KhiXtprsSyiECg5QdvasCZVIpplwkqaB1GiqDLQT4cg+kRLWAM0kcqNYH9BXOltWGiZ8yrFFaNErz9Ht1BBSkP9eD+7oq2lVpJAlc/JWmADrfnu3Dpu97dRtLibu5WTDE2PsLs5IbPNRj0s/V2r+WZVIiYp+ijnPJIQOEop9y3MvgBmAhKw3y0ECoWbG0UvLledMoK9TdY0n3odlg==
+ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=wvlTfWPfj3/WsoJsA/QXjScbTOF7ccq6yfDWGs3vQxY=;
+ b=AvJDVASMlo8Q7HaQOTXtWbHFVXcgIHSgcQqIuHKiKQsaAORDYOnxPOg4ZOUtzhU5jhIvHwfhgTsa2br1RHao9qNa3fhzkPVXScxMFuu05roRfGwYDdIsVj3U3iWvRG5gXck3eR2VkNvgOAXmMzisXNNnc79gMbByoKu3F0QKefmYyWqahZ+o/SaNHj3OHIkn4x4gYHwrA9ejhg+8Zmnj8zOTOs/yqVvpmFQwCv3nKzdUIP4PxKPvSbmmdg32J2WGaY7Z+O9BJATs99AL72WaOIlTVj1wIBFoJYZSv26btGWU5ILfV6IN5xxE2ojpyZYRl5xEJCNDSH0pcbLi+wVaAg==
+ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is
+ 2a01:111:f403:c20a::7) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=pass (signature was verified) header.d=vodafone.com; arc=pass (0 oda=1
+ ltdi=1 spf=[1,1,smtp.mailfrom=vodafone.com]
+ dmarc=[1,1,header.from=vodafone.com])
+Received: from YQBPR0101CA0262.CANPRD01.PROD.OUTLOOK.COM
+ (2603:10b6:c01:68::24) by CH3PR17MB6961.namprd17.prod.outlook.com
+ (2603:10b6:610:15a::10) with Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Thu, 30 Apr
+ 2026 13:44:20 +0000
+Received: from QB1PEPF00004E09.CANPRD01.PROD.OUTLOOK.COM
+ (2603:10b6:c01:68:cafe::63) by YQBPR0101CA0262.outlook.office365.com
+ (2603:10b6:c01:68::24) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9846.30 via Frontend Transport; Thu,
+ 30 Apr 2026 13:44:20 +0000
+Authentication-Results: spf=pass (sender IP is 2a01:111:f403:c20a::7)
+ smtp.mailfrom=vodafone.com; dkim=pass (signature was verified)
+ header.d=vodafone.com;dmarc=pass action=none
+ header.from=vodafone.com;compauth=pass reason=100
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 2a01:111:f403:c20a::7 as permitted sender) receiver=protection.outlook.com;
+ client-ip=2a01:111:f403:c20a::7;
+ helo=PA4PR04CU001.outbound.protection.outlook.com; pr=C
+Received: from PA4PR04CU001.outbound.protection.outlook.com
+ (2a01:111:f403:c20a::7) by QB1PEPF00004E09.mail.protection.outlook.com
+ (2603:10b6:c08::127) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9870.22 via Frontend Transport; Thu,
+ 30 Apr 2026 13:44:19 +0000
+ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;
+ b=mHI6jwnufkboeWbHFllT0yMwgvSCskb1exvxFYahxUg9beMz9YPzkxVHKSNsj1Lqvh5YSt+yJlnJxm5oijcUR3/LL7mta7YnZAvVQGsvs89btjQqYLfq488G6lroOxSTsiHUEgf5qKO73lz30N/1FNfp81vlDrwUlVIdDtQdVRtPvT45ADZ8RSxMbt2cxN28KANgzmIhKh3exiZTqUe6nQ/W+zAr/V5y8yasj/Szjjpf60ybKhauKMhwN0t3cPL/pmHhytspR5r9yxPU5X3vaD7FEuXYIm4VS2n5nY4FhqHfpZ5gWNzeXj+ru+GFE9zXuZhTUMbelHsVlEsB8XhSNQ==
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=wvlTfWPfj3/WsoJsA/QXjScbTOF7ccq6yfDWGs3vQxY=;
+ b=ne0X0re4ltjR3N4fll1TuiPE+JASByCrme4YCeJ4BGgNrZdfcHIqXU1r/cYjjcGKWMbfSfHQrGcmK9xVXccHFiEW5noAno4BU2I80EeCa9gHu+PPxBIen0rC6YQ5XKDVydtPGUWDdHDuxPpJPjOw3OMVH7gxh9WZLgT7GXoWteAjfIBvE4l2JLkFoYZxTlbkdAEB2QNVi3aEt317Eac+Zq6ZW6YmmSbH6hbJaBnTYqWiHz9XjMceObcM3K8Jrf3frXaLS8YGdd40lijzGmjdVxgUESNV3bNXlDy44lUmqkwnRTO6OhiQZvj/ORI0kwZ+wd/VeI3b2lJuZE7RuwmqAg==
+ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is
+ 195.232.244.47) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=none (message not signed); arc=none (0)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.com;
+ s=selector2;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
+ bh=wvlTfWPfj3/WsoJsA/QXjScbTOF7ccq6yfDWGs3vQxY=;
+ b=I/geIsASk5nflRZmjTtx/KNvfjrzPx7FTj1Upex+qyenaV6h/0+5ExD6cUv2wPYjYUxfo3LbHzt/gLXMgrLcPiBV6uGyKGnIvVHnMaaPQQ1l3Zw7rP8zLCvfzF47vyr0ZMHYu1wInknQ1M8neAdXqfq5FfOshZdyQost1QNBNjX5pQY+0x3eC/9Dy2tGlaTyDVnUdBPj8sF/wKHTAY1J1svWZzS0cvajiOQZuJaNitOnFwtHVWfy/a6xbiOD34MyLMjTGCsZZcVtZxacCg9J8hfuc89V6uRozyzl7ei+ZFL9DBI9R3HBGZJ9UUIDkPARUd2FWK8m0rGFFjB8LOaqDg==
+Received: from DUZPR01CA0157.eurprd01.prod.exchangelabs.com
+ (2603:10a6:10:4bd::21) by MRWPR05MB12995.eurprd05.prod.outlook.com
+ (2603:10a6:501:88::24) with Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.20; Thu, 30 Apr
+ 2026 13:44:14 +0000
+Received: from DU2PEPF00028D11.eurprd03.prod.outlook.com
+ (2603:10a6:10:4bd:cafe::a8) by DUZPR01CA0157.outlook.office365.com
+ (2603:10a6:10:4bd::21) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9846.30 via Frontend Transport; Thu,
+ 30 Apr 2026 13:44:14 +0000
+X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 195.232.244.47)
+ smtp.mailfrom=vodafone.com; dkim=none (message not signed)
+ header.d=none;dmarc=pass action=none header.from=vodafone.com;
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 195.232.244.47 as permitted sender) receiver=protection.outlook.com;
+ client-ip=195.232.244.47; helo=VOXE02HW.internal.vodafone.com; pr=C
+Received: from VOXE02HW.internal.vodafone.com (195.232.244.47) by
+ DU2PEPF00028D11.mail.protection.outlook.com (10.167.242.25) with Microsoft
+ SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
+ 15.20.9791.48 via Frontend Transport; Thu, 30 Apr 2026 13:44:14 +0000
+Received: from appsmtp-north.internal.vodafone.com (145.230.101.14) by
+ VOXE02HW.internal.vodafone.com (195.232.244.47) with Microsoft SMTP Server id
+ 15.2.2562.37; Thu, 30 Apr 2026 15:44:12 +0200
+Received: from GBVLS-AS360 ([10.196.150.7]) by appsmtp-north.internal.vodafone.com with Microsoft SMTPSVC(10.0.17763.1697);
+ Thu, 30 Apr 2026 15:44:12 +0200
+Date: Thu, 30 Apr 2026 13:44:12 +0000
+From: Network Change
+Reply-To: Network Change
+To:
+Message-ID: <447323991.58489.1777556652379@GBVLS-AS360>
+Subject: 3rd Party Essential Works CRQ000001325565 Affecting ACME CORP
+ Services
+Content-Type: multipart/alternative;
+ boundary="----=_Part_58488_194312060.1777556652379"
+Return-Path: networkchangemanagement@vodafone.com
+X-OriginalArrivalTime: 30 Apr 2026 13:44:12.0740 (UTC) FILETIME=[6DCA8840:01DCD8A7]
+X-EOPAttributedMessage: 1
+X-MS-TrafficTypeDiagnostic: DU2PEPF00028D11:EE_|MRWPR05MB12995:EE_|QB1PEPF00004E09:EE_|CH3PR17MB6961:EE_|CH3PR17MB6987:EE_
+X-MS-Office365-Filtering-Correlation-Id: acd9fb11-a058-4388-340f-08dea6be9488
+X-MS-Exchange-SenderADCheck: 1
+X-MS-Exchange-AntiSpam-Relay: 0
+X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230040|36860700016|82310400026|376014|1800799024|8096899003|18002099003|56012099003;
+X-Microsoft-Antispam-Message-Info-Original: LiY4cMbu6HhgxRZ62ZI2WyO/+fRwT/FuTOm6cmJdTPynNkQHWOfVRBwo/qKhVORVkWbyEo0tEZ3VHwABXG6+828WF1Lav9Lg1ioskTFiSkpbKLf86D7JOHv2QF8qSZlU3orr+mbTputN9PrrHbKUPDwIG3105DCf0m5MYSHSMprM60F5diOY4ZbI56eWnGoB6dcAx4X6SxLH2a8weEvhP0MgQjmgFDi4TeRxrIH/zckuSxGLxVxXf8ar7xqBuYOuXI0VQv0zRd752ex1a8VyXdFAIK3583tqKoyEko2QX8GAwWD/g3BmmejvBSTy7kvXU+WBt5uY7HMvBHmaRErRyahlaLPxMFS3ueo6Q9HfwiTXpDxcPpD5y9RrmHpCH5hCpS0/fGpKmWSjaPQrzO22vDOm7rShNB8E1vwmvkvnSvUXiJwUY629Fcbrouj6wYhXDNDesdbbd4sYDJaV13wsL06677KOOmwWlY9dkOBCpbsmPh0G8h1zXAXpqNt+8Sii9KqjcXZQF9B7gARAXeUUX1+id7w9iB1/C1OEvnwgOe8FXvOaZC+xrm1qMKeboOnxBNbru/iMecSwZR8vAzyZFT153I2G34XOWmt+HV0BfWeZYgwPvy/bZvtAFjClFrh9Op2W8i5kK3Vqa+DfEnLkzW044Oy/Q1EdnVN+kjvcqiPiYArckoSLJ1Eg8+dX8IQzOyttYcpWZipGSMmUaOqb+nWgUpGvlAz+Un+kFopS8545VtoLzzauNpAwaSZcOmBFrT6fOYuHd6i5+ByGym7Ugg==
+X-Forefront-Antispam-Report-Untrusted: CIP:195.232.244.47;CTRY:IT;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VOXE02HW.internal.vodafone.com;PTR:msedge2.vodafone.com;CAT:NONE;SFS:(13230040)(36860700016)(82310400026)(376014)(1800799024)(8096899003)(18002099003)(56012099003);DIR:OUT;SFP:1101;
+X-MS-Exchange-AntiSpam-MessageData-Original-ChunkCount: 1
+X-MS-Exchange-AntiSpam-MessageData-Original-0: wEZ+XQfZXEnKrdUmUIqtSq5wcZosRM1W+f7KQnOYozdRwp4XoJvDh2HYJLAvVhnnQaLZTaTnWq8wNWlL2H9NO0JCBIvKW7fR28vYf9NeiDd19LBXgeSpysOL1xrfKWbWG7+A43yolDZY9l7VT1JKJljvFxT03mhTH4Cgm3vMKGiaUr0KacWnQQWA7ZGfPmLlGUYeNTRAKNKirmhtsrzV/b9SJxRSUcE77I+nMiSlKL2KkTmYWkpRmkxtS44f6E+TrUkhk08+0gyXOYslb8jqUwWF/uoCClvWDDx9WdvxKFbcOxqGPoCRlG9KS++KzObxrC3Ymcp1FFJ46rGc1Ci6EUP2jNAhjfZ7Kdy7Bg1LPjnTG/c4ZPyk7e7m7gp6ahu0ZpJGjmzgIlJ7K3wm0bKll0VYZRJ1nbdLMeJZEjl5k40S/kohpZ+dM6l28ohw9/0J
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: MRWPR05MB12995
+X-MS-Exchange-Organization-ExpirationStartTime: 30 Apr 2026 13:44:19.9140
+ (UTC)
+X-MS-Exchange-Organization-ExpirationStartTimeReason: OriginalSubmit
+X-MS-Exchange-Organization-ExpirationInterval: 1:00:00:00.0000000
+X-MS-Exchange-Organization-ExpirationIntervalReason: OriginalSubmit
+X-MS-Exchange-Organization-Network-Message-Id: acd9fb11-a058-4388-340f-08dea6be9488
+X-EOPTenantAttributedMessage: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1:0
+X-MS-Exchange-Organization-MessageDirectionality: Incoming
+X-MS-Exchange-Transport-CrossTenantHeadersStripped: QB1PEPF00004E09.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Transport-CrossTenantHeadersPromoted: QB1PEPF00004E09.CANPRD01.PROD.OUTLOOK.COM
+X-MS-PublicTrafficType: Email
+X-MS-Exchange-Organization-AuthSource: QB1PEPF00004E09.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Organization-AuthAs: Anonymous
+X-MS-Office365-Filtering-Correlation-Id-Prvs: e4fb635c-18c0-4e19-e9e7-08dea6be9157
+X-MS-Exchange-AtpMessageProperties: SA|SL
+X-MS-Exchange-Organization-SCL: 1
+X-Microsoft-Antispam: BCL:2;ARA:13230040|704161411799003|12012899012|2092899012|3072899012|35042699022|8096899003|19002099003|18002099003|16102099003|57112099003|55112099003|13003099007;
+X-Forefront-Antispam-Report: CIP:2a01:111:f403:c20a::7;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PA4PR04CU001.outbound.protection.outlook.com;PTR:mail-francecentralazlp170130007.outbound.protection.outlook.com;CAT:NONE;SFS:(13230040)(704161411799003)(12012899012)(2092899012)(3072899012)(35042699022)(8096899003)(19002099003)(18002099003)(16102099003)(57112099003)(55112099003)(13003099007);DIR:INB;
+X-Auto-Response-Suppress: DR, OOF, AutoReply
+X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Apr 2026 13:44:19.6925
+ (UTC)
+X-MS-Exchange-CrossTenant-Network-Message-Id: acd9fb11-a058-4388-340f-08dea6be9488
+X-MS-Exchange-CrossTenant-Id: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1
+X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=68283f3b-8487-4c86-adb3-a5228f18b893;Ip=[195.232.244.47];Helo=[VOXE02HW.internal.vodafone.com]
+X-MS-Exchange-CrossTenant-AuthSource: QB1PEPF00004E09.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-CrossTenant-AuthAs: Anonymous
+X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR17MB6961
+X-MS-Exchange-Transport-EndToEndLatency: 00:00:07.1036869
+X-MS-Exchange-Processed-By-BccFoldering: 15.20.9870.000
+X-Microsoft-Antispam-Mailbox-Delivery:
+ ucf:0;jmr:0;auth:0;dest:I;ENG:(910005)(944490095)(944506478)(944626604)(920097)(930201)(20251009189)(140003);
+X-Microsoft-Antispam-Message-Info:
+ =?utf-8?B?dVdEOUllTjBZTFZFbWpKa3NXOXVtUFpqRU84dVprRUZQVEd1amk5SDZBR0ln?=
+ =?utf-8?B?ZGVJL0Uza2V5b081eE1mLzRoWENldGVVT3NEenhVTktiVGpjd1MrYnpGOVRF?=
+ =?utf-8?B?MWcxdzk4SW9keFAwVUl1NG1zSmpNeTU2RGhGbVFLTGhqclB0MkNjWmtRaEE0?=
+ =?utf-8?B?UTk3dDc0RUI2TDcrR0JRZ01ScTM2Ly91bjJ5L1JSenpCQjZPQkx1NmEvTC9s?=
+ =?utf-8?B?Yzl4RTJxdjV4TTBBcjVnSEoxczFwdVJzUnhER3RNaXg5aTVTRG1xU1FaVzZD?=
+ =?utf-8?B?emFsTWZab1JLMmF2STBTZ2NuRGd4NzVkUTRSMzZsRGNOOStWZmwyNjZtSjNP?=
+ =?utf-8?B?L24zV0w1MVlwYVZ3VzhPU1pNc3hNSWpGSDUrQXhHSm4rdHNna09mT0lDWEE3?=
+ =?utf-8?B?RTBFWjBzcExZNW1jbEhSWFBuWHF5cDNwT3JmNmtnRkQydkltckpPNlE2bDNm?=
+ =?utf-8?B?VEdLcStPVnZiYzQ5SGNRUmRITlhMMVBSM0tMb05SMjdva1FhWGpkMGI2M3NJ?=
+ =?utf-8?B?OUpmWHhtU0dCaEtwdXVhcG5ZVU5PQmZOYVI3V2kxbGpkUGo4L2F2U2hqTEE3?=
+ =?utf-8?B?b2JzNTR6aVN6SUJ3WUM1Vm11YnBkbDNUaElwd3JDdy9wUmZuMlVUNmRTVGRJ?=
+ =?utf-8?B?T2gwM00wbGx1U2oxUWlCenhja1MvZ1ZrajRGM3JUcWhoR01jNGowZ053N0U3?=
+ =?utf-8?B?cS9OMGVrcFNGZnJLT0VEMy9HVWdsWFp5b25rdkNSV3JiRDZVdy9GR3hhU29s?=
+ =?utf-8?B?T0dDQVlzc3h0RUdZMHhYZm82WFZCMkdIUWY4SkhWSXNJTG02NzgrbmtGVmFj?=
+ =?utf-8?B?blg1V1MwY3dtZFNNUjY3VXlQNDBzWVYzOUQyKzlEd3dXY3pyOXZ3UnhNMFRv?=
+ =?utf-8?B?SWZjaW05UjRpWmZCNStLRG0yTjJ2OVZwbVh2MzRYeStkQ3RESHFaTHI2N2dq?=
+ =?utf-8?B?TmhsSnRibUlFd0szbnl0QWFYYzVvbWhFdWN4a3lKempYNW51UXh3WFVLdjBI?=
+ =?utf-8?B?ZTBoZTU2VnJGQVFyUzFFMnA3M0tpcVNtNHJvRDdnUUlYbmY2bThKNERIT01Z?=
+ =?utf-8?B?UTY1UW9YcDRGeFpQNElaNzlYMUhrWm5Fek9maVVYUzVZUXRKQnRuajBITGtJ?=
+ =?utf-8?B?L1JqTlZkY3JNalFzK2tMNi91VmM4NVpmZHlqWkI4TWFpTkpFaUJ3UVVCSHQ5?=
+ =?utf-8?B?em9oU1Uvb2xCQlQ1dXJCTEN1dzlsZnRyd2QzZFFTVDV4VVo1OGJYTE5PWjQz?=
+ =?utf-8?B?TkllVllMWldkbERTbnJzWjdpNXFESkdsay9xb3pEY2pITTZhT1dRcGl4c2ZR?=
+ =?utf-8?B?UHZtNElKdFVvVCt0bk1iRUluWkdlckZUWkt4ZXlQa0ZaTnF1ZFdveHBnNWNj?=
+ =?utf-8?B?M3dIa1NPbzlVNnpwd0VQMWpuZDFyT0hqb1JZVFVaOVNkLzhLQ1prWjJ2aytX?=
+ =?utf-8?B?cGRDZjRKcm8xczZHUHBKQVN1cmtyQk04Qm1abmlSZllXdGVBWlcwSXlXTEgx?=
+ =?utf-8?B?ZjZSdTlQOEtySTlkUHZ4ZUF4SXo3VVA5T2lvQ2lLWUVIUDVDemtnVnI4QXAv?=
+ =?utf-8?B?Qm9VaUdZd1ZkdVJEU1kvUHhrWnBDYm9pTkM3WDZMcytCNXB6N3hkM3FmaHVR?=
+ =?utf-8?B?MjFkUU4xb0ZyVEtGQVJxUmk5Ymp2ZDlDczA1Ykd6anFXaGVaZDZqN1RPQ3NS?=
+ =?utf-8?B?TkxhaHdHV2dlS1l4Q2QzZXo0R1pJYVYzaEkxOGdjamNIeTI0Zkd5dnBVSGZx?=
+ =?utf-8?B?UmMzMFVCL3E1dGtHT2RJQTBqL2o5cUtjTUVFb0lON0VGRUp4ZDh1MkJVV1hD?=
+ =?utf-8?B?b2ZPZmxyN1BxRkplcWxmRjN5dklnaTMwbzZReHBxWkVYVU5ETlJDdVI2N1BR?=
+ =?utf-8?B?cEZpbkEwYkhUeWpsTkRuSk0yQ2ZMVU5JWkVxa0xsTVJCZWZlbHBQMDFMckZE?=
+ =?utf-8?B?TDUrV0dTN1V4M05OM3AxeVFyZmRSVXIwSXNkZXVubVk1UVVReVlFTkhjSVJS?=
+ =?utf-8?B?a3BZSk50SmdsL0tuSHMvWTNwQnpnZlVVUm91dCtjclVhcDJQdEMvblZkR1pn?=
+ =?utf-8?B?WmZSL0kzMElEaDZ4Z0ZrbEpWczJyOFpNcjhuWlZWcHEvWHUwc0FVMGVPdUds?=
+ =?utf-8?B?R0VWUnc5Z0crMCszcUMzQ3ArLzhWVGw2SkUrZUJQbDFMZERwWVVTV0tLNnlj?=
+ =?utf-8?B?azhMc0lpZHNNY1BpVERrZDdyVmw2bGFFWWhJa3A3NlZ5a0NxWk5SeXRuN254?=
+ =?utf-8?B?azFJMWZzWVVCMUhhaTFVODYrSkczekZaS0VxVENWVWR6ZHFMUjNJa2krd1Fo?=
+ =?utf-8?B?aFdYcGQ0WWIzU08zcHVadGlnM1FMMk50aGlCbjAyOXgyUmhZYi96dS9KVDJT?=
+ =?utf-8?B?TndkMHJWeDQ1T3ZsWlovV2dDTDNlUVhPUHAvck02NDNBcURQaVpnWk40a3pL?=
+ =?utf-8?B?TGQzRWFOT2U5WGU2R2QwaXNSMWU2SGJZNmFBSDNuVHI4RGkwQWE0MTZjQWVH?=
+ =?utf-8?B?cFlYdnM1UGhyZGhVa0dnWmFkK2VNb0JxM0pjdFhuTlFQbWhlM2JQRmZpNmJ4?=
+ =?utf-8?B?dDdYYUpsUXB5V0FYZ2dRZk1kdUlqaUwrZUxndU5YRHc0djF6Y2dQeFJyN3Vs?=
+ =?utf-8?B?czcyZzlIUFExTHlLQUVNTUwwK3JHRFBEREtna1NLbXZ5VVhONTFDd1g3NHhS?=
+ =?utf-8?B?Y09JR0VKMUhDZEZVWnF4dzJ1QllqWFZ2akdCakxQcFVsdlE0S1h2aTcreW4y?=
+ =?utf-8?B?bzZCM1R6ODF2RnB0Sk5GaThWNmYxQ2pxNi80SVYwbzQ4RHp0M1dia0ZaMXJH?=
+ =?utf-8?B?MGdWMmdKdkY3U0U5WnJRZW8yWExKUksxWHQzVitxV2VBQU9LRUMxZDNtN2h4?=
+ =?utf-8?B?OTJuaVRmUzZRRUI2MDFKV3FIT0hpcVIrWkdYUmtBeFlRdEJvbUwrNkZCbStE?=
+ =?utf-8?B?NXBBMFY5dDdtTHRzQ3BDMVlDQnpxc1QvNG9tRmRVUzVRNGJUellIREk5NGUv?=
+ =?utf-8?B?WlNBcC9IbzlWNnU3L2dZRVlZVUFGSXFVYjMzRkxxU2FkZjUvTVhCZHBZY0xB?=
+ =?utf-8?B?aTc3ZzcwUUovVm91MmtJN3B6MlY3M1RESU5Nb1FqTzNMSk5YdHNiYVY5MGl1?=
+ =?utf-8?B?YWQ4OGpPd2F3S3M4TEhDZ1hhWit2Y0IxbkpHM3cxaFM2dm5wRmVaOFhrKzg2?=
+ =?utf-8?B?TmtWcFJrV1ZNcFdWaitVV25EdVY0U3RBbWh2S0JCM211aU90TDJqRWx1Q2R0?=
+ =?utf-8?B?ZmhEVlhZUVhBSkJVSHVHQVMzdWRZdkxiUHZrUE5KNWdPdFhtWk8zQUdha3do?=
+ =?utf-8?B?QTl4bDhLUmFRMmFKaE5wNkRqY3NlY1RxcEt2eUd1S3RmSXhPNE1TSmZkWFpk?=
+ =?utf-8?B?T3JqR0h0eE9aUUtSWG00dlNpd2N4TEd5TlJscmZBR294S3BEbXNOd2xHUjg1?=
+ =?utf-8?B?TmJSdytobm9KL05YcGU5WGs1SCtDYXVncmhCVTh1MjZZZ1lwbFBhRmZzZko1?=
+ =?utf-8?B?enJPN2pId2JBc2dLY3BjREJIR3U5UW95aVlJUkQ2VUlieFdlejRwb3NqVGl6?=
+ =?utf-8?Q?vIbHP3hUSlm85t?=
+MIME-Version: 1.0
+
+------=_Part_58488_194312060.1777556652379
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Vodafone UK - Technology Operations
+Essential Maintenance Notice
+
+
+Dear ACME CORP,
+
+Please see below details of Essential Works: CRQ000001325565
+
+Detailed Description of Works:
+3rd Party Essential Works to carry out maintenance to move their cable to n=
+ew reroute Due to road construction works
+
+Scheduled Start/End Date & Outage Window:
+05/05/2026 20:00 to 06/05/2026 04:00 UTC
+
+Impact Assessment:
+Loss of service for 480 minutes
+
+Contingency Date:
+NA
+
+Services Impacted:
+
+Services Affected Customer Service Impact Address Service Typ=
+e Service Model Customer Reference Node
+X0013337A ACME CORP Loss of Service 15 PIONEER WALK, 03-02 PION=
+EER HUB, 'SINGAPORE, 'SINGAPORE, 627753 >>> PARIS EQUINIX , 114 RUE AMBROIS=
+E CROIZAT 93200 SAINT, PARIS, FRANCE, 93200 Cross Inventory Service/S=
+TM64 null Refs: Orig Cus: MORI Node : PARN25-BlackBox-FRASTD003 >>>=
+ SNGN11-BlackBox-SGPSGP004
+
+
+
+Issues regarding circuit identification, please contact your Vodafone appoi=
+nted Service Manager/ Account Manager.
+
+The information given is what is held in our records and should have been p=
+assed to you when the service went live.
+Thanks
+Vodafone UK Fixed
+Change Management Analyst
+Change Management
+Email: networkchangemanagement@vodafone.com
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limited a=
+nd Hutchison 3G UK Limited and this email is sent on behalf of Vodafone Lim=
+ited and/or Hutchison 3G UK Limited. The message and any attachment(s) are =
+confidential, may be legally privileged and are intended solely for the att=
+ention of the addressee(s). If you are not the intended recipient or you h=
+ave received this email in error, please notify the sender immediately, del=
+ete it and any attachments from your system and do not copy, disclose or us=
+e its contents for any purpose. This transmission cannot be guaranteed to b=
+e secure or error-free. Any views or opinions expressed in this message are=
+ those of the author only.
+
+Vodafone Limited. Registered in England & Wales | Company no 01471587. Voda=
+fone House, The Connection, Newbury, Berkshire, RG14 2FN. Authorised & Regu=
+lated by the Financial Conduct Authority for consumer credit lending and in=
+surance distribution activity (Financial Services Register No. 712210).
+
+Hutchison 3G UK Limited. Registered in England and Wales | Company number 3=
+885486. Registered Office: 450 Longwater Avenue, Green Park, Reading, Berks=
+hire, RG2 6GF. Authorised & Regulated by the Financial Conduct Authority fo=
+r consumer credit (Financial Services Register No. 738979).
+
+VodafoneThree is a holding company of Vodafone Limited and Hutchison 3G UK =
+Limited, see www.VodafoneThree.com to learn =
+more.
+
+------=_Part_58488_194312060.1777556652379
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+
+
+
+
+Vodafone UK - Technology Operations=
+span>
+Essential Maintenance Notice
+
+Dear ACME CORP,
+
+Please see below details of Essential Works: CRQ000001325565
+
+Detailed Description of Works:
+3rd Party Essential Works to carry out maintenance to move their cable to n=
+ew reroute Due to road construction works
+
+
+Scheduled Start/End Date & Outage Window:
+05/05/2026 20:00 to 06/05/2026 04:00 UTC
+
+Impact Assessment:
+Loss of service for 480 minutes
+
+Contingency Date:
+NA
+
+Services Impacted:
+
+
+
+
+| Services Affected |
+Customer |
+Service Impact |
+Address |
+Service Type |
+Service Model |
+Customer Reference |
+Node |
+
+
+| X0013337A |
+ACME CORP |
+Loss of Service |
+15 PIONEER WALK, 03-02 PIONEER HUB, 'SING=
+APORE, 'SINGAPORE, 627753 >>> PARIS EQUINIX , 114 RUE AMBROISE CRO=
+IZAT 93200 SAINT, PARIS, FRANCE, 93200 |
+Cross Inventory Service/STM64 |
+null |
+Refs: Orig Cus: MORI |
+Node : PARN25-BlackBox-FRASTD003 >>=
+> SNGN11-BlackBox-SGPSGP004 |
+
+
+
+
+
+
+Issues regarding circuit identification, please contact your Vodafone appoi=
+nted Service Manager/ Account Manager.
+
+
+The information given is what is held in our records and should have been p=
+assed to you when the service went live.
+
+Thanks
+
+Vodafone UK Fixed
+Change Management Analyst
+Change Management
+Email: networkchangemanagement@vodafone.com
+
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limite=
+d and Hutchison 3G UK Limited and this email is sent on behalf of Vodafone =
+Limited and/or Hutchison 3G UK Limited. The message and any attachment(s) a=
+re confidential, may be legally
+ privileged and are intended solely for the attention of the addressee(s).&=
+nbsp; If you are not the intended recipient or you have received this email=
+ in error, please notify the sender immediately, delete it and any attachme=
+nts from your system and do not copy,
+ disclose or use its contents for any purpose. This transmission cannot be =
+guaranteed to be secure or error-free. Any views or opinions expressed in t=
+his message are those of the author only.
+Vodafone Limited. Registered in England & Wales | C=
+ompany no 01471587. Vodafone House, The Connection, Newbury, Berkshire, RG1=
+4 2FN. Authorised & Regulated by the Financial Conduct Authority for co=
+nsumer credit lending and insurance distribution
+ activity (Financial Services Register No. 712210).
+Hutchison 3G UK Limited. Registered in England and Wale=
+s | Company number 3885486. Registered Office: 450 Longwater Avenue, Green =
+Park, Reading, Berkshire, RG2 6GF. Authorised & Regulated by the Financ=
+ial Conduct Authority for consumer credit
+ (Financial Services Register No. 738979).
+VodafoneThree is a holding company of Vodafone Limited =
+and Hutchison 3G UK Limited, see
+www.VodafoneThree.com to lear=
+n more.
+
+
+
+------=_Part_58488_194312060.1777556652379--
diff --git a/tests/unit/data/vodafone/vodafone1_result.json b/tests/unit/data/vodafone/vodafone1_result.json
new file mode 100644
index 00000000..f8aef000
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone1_result.json
@@ -0,0 +1,16 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1778040000,
+ "maintenance_id": "CRQ000001325565",
+ "start": 1778011200,
+ "status": "CONFIRMED",
+ "summary": "3rd Party Essential Works to carry out maintenance to move their cable to new reroute Due to road construction works"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone1_result_combined.json b/tests/unit/data/vodafone/vodafone1_result_combined.json
new file mode 100644
index 00000000..ea293ca1
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone1_result_combined.json
@@ -0,0 +1,21 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1778040000,
+ "maintenance_id": "CRQ000001325565",
+ "organizer": "networkchangemanagement@vodafone.com",
+ "provider": "vodafone",
+ "sequence": 1,
+ "stamp": 1777556652,
+ "start": 1778011200,
+ "status": "CONFIRMED",
+ "summary": "3rd Party Essential Works to carry out maintenance to move their cable to new reroute Due to road construction works",
+ "uid": "0"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone2.eml b/tests/unit/data/vodafone/vodafone2.eml
new file mode 100644
index 00000000..0ba320a4
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone2.eml
@@ -0,0 +1,390 @@
+Received: from MW4PR17MB5715.namprd17.prod.outlook.com (2603:10b6:303:12e::21)
+ by CH3PR17MB6987.namprd17.prod.outlook.com with HTTPS; Wed, 25 Mar 2026
+ 14:21:30 +0000
+ARC-Seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass;
+ b=HeRlsN0Qhbxe1qpzMfeaE5EX2QXsHxygS+jXvpRm2zwoKaAs5SsFDQFBrPVGnVuWqVA9PmDA07XdcnvatscvtADIp5UC7rQT3xTqrgoqQARwLCu9CPKbWclDx/vKT0zOlyH2yW8Sj/J9f3oT0BldE2p29jFdVWe+9xUbm6/aymEOFdtk1+Sm5A9oFRXF9YvmlxKuNSF8B0Ard9IgrXu8vD/pqOOkOdild4b1SNL4boC0hMEl5ongD6rIUyFESYxCHEw/efig6oYymDTacs+CDtbbkzuUyK1KFi454cGh8WAdxma3zTqgCr1KkFC9KQ/NUkVEX5WTEEvKG5vyO4kvAQ==
+ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=27KlzWLbn6ptVEw/6+2sGCOeIxNt+eHmlLonN19w+HQ=;
+ b=qjQ4XJV2jb7LKwI17gy6Z/HNlT109QsABG5FOIunq/cpcpxq98Z1gROtfnLGZO9oC1CtvBI2Iw2dT56xf9rw6nzmiUVPZpHY2HycDNNwKl/TEG/bRf/ZVwc+osAf7oU2seGhUOBpQxdoR5k0RruKlJj8f9JoQWhEkK99UVqw805s+iy0U1vjdv0xVC6CasvzHqCAvNVTJZwCo2rGvjzlcuo2hALl5KRK7qjkdK3qb92PofnxY/PXuaX5WlHXteLpPmz2CCzQH6tdbyhHl76zGfh4z2l9rCZJvJ4irFm7AZHITFAe8WCtx3ORe5pOiLXOhZE4wV6hrNqA66HxmXYyvQ==
+ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is
+ 2a01:111:f403:c201::1) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=pass (signature was verified) header.d=vodafone.com; arc=pass (0 oda=1
+ ltdi=1 spf=[1,1,smtp.mailfrom=vodafone.com]
+ dmarc=[1,1,header.from=vodafone.com])
+Received: from YQZPR01CA0136.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:c01:87::7)
+ by MW4PR17MB5715.namprd17.prod.outlook.com (2603:10b6:303:12e::21) with
+ Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9745.20; Wed, 25 Mar
+ 2026 14:21:27 +0000
+Received: from QB1PEPF00004E0C.CANPRD01.PROD.OUTLOOK.COM
+ (2603:10b6:c01:87:cafe::a3) by YQZPR01CA0136.outlook.office365.com
+ (2603:10b6:c01:87::7) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9723.32 via Frontend Transport; Wed,
+ 25 Mar 2026 14:21:27 +0000
+Authentication-Results: spf=pass (sender IP is 2a01:111:f403:c201::1)
+ smtp.mailfrom=vodafone.com; dkim=pass (signature was verified)
+ header.d=vodafone.com;dmarc=pass action=none
+ header.from=vodafone.com;compauth=pass reason=100
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 2a01:111:f403:c201::1 as permitted sender) receiver=protection.outlook.com;
+ client-ip=2a01:111:f403:c201::1;
+ helo=AM0PR83CU005.outbound.protection.outlook.com; pr=C
+Received: from AM0PR83CU005.outbound.protection.outlook.com
+ (2a01:111:f403:c201::1) by QB1PEPF00004E0C.mail.protection.outlook.com
+ (2603:10b6:c08::114) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9745.21 via Frontend Transport; Wed,
+ 25 Mar 2026 14:21:26 +0000
+ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;
+ b=QjiA7+6NG1oA/qo6HDSmAJFIJgWa2spkf3MWsqilbiPhCuTzMWq+yaG/97fkaW9X63NHm1+Q4wVaVuksSL/fp/Q+SWS+15GChyHjeOsqPEjuGzwjdAFT2WagXAoIp2pjvZBOSPq04CUMMFy/db0ZIhcgWJbeSjlo6v1XHejB+CDUi2b0CoOuyiHrDMFsrn5EuDp4lo22zYLqKxjNhsh0YhGKIuPpRe1se/yHqpVL5Eosnqdeyg9Me3bY6gs/ud2tKBhMMrLdRWJvmRwW4sQiE+0qaRtMhoX9nJ4wPgj1c1MKseowvnK4BH5Y0JSDcSxos/WiDHLQyWajH1TXT3CIYQ==
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=27KlzWLbn6ptVEw/6+2sGCOeIxNt+eHmlLonN19w+HQ=;
+ b=Y3lpe93mjdLLSYe6NA17WhdKnjEoxOjduiyNo+CaXOIiNb1u5cetgirg7uoAqLr52I358X8Rz5FKLZjoHuJJ9jyxNvJJqPjpmnss492TIxUz7jMkbirwelx1Sdl/o5uEcweKzwl1bpXJ0hiWIg9HxtUHMqltHn8tslGgwAos7YwmMGVPghoVedVH0u+E+5g9aBLKnOG1BwwamHkuj/ep+s5NMv9fDA+e7S7Jwi1eSlqKVm84R34JHBV14zMgMA6tmPZ/TMBRVnT2y/omgC/OBLnY/bAEY7Kr4SPwoAUbjIPFRKMGbpV4O3DGw3iWyBXgLQRVpFAiFhlKJaujOuf/Ug==
+ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is
+ 195.232.244.48) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=none (message not signed); arc=none (0)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.com;
+ s=selector2;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
+ bh=27KlzWLbn6ptVEw/6+2sGCOeIxNt+eHmlLonN19w+HQ=;
+ b=VPzZy/RchiX4iqQj8/mbjT0dhzGZyauj/RK2oCymQ82LkV99Vvv+JOZBaiyT9Mr1czSFDLlyoQ8zL0cuK5Yvsyj7/6VUEJx9p2xggZse3zSFEaOOhxaRJOuRqZ4IFuwHSTKxaHPADJNl/iaBv1ETZsRAej7Em/IYuwJoPD1fMkxYbGFS0G/WAlUoNnIKg53W1GJ35KVXMBCpBk2lT9MBLzYelOsry4hTtLHqWi8sMEANzmEO7ylEniH8lI9F5A7NWxxkDtoabibs7NzU/0rYN2+mLJo2TnWh0KgN2BpMbh3PlQqgiS8HBBduAY4RTt0kIzqU+/zufyugJFDfkEGvXg==
+Received: from DUZPR01CA0214.eurprd01.prod.exchangelabs.com
+ (2603:10a6:10:4b4::19) by AM9PR05MB8828.eurprd05.prod.outlook.com
+ (2603:10a6:20b:437::14) with Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9745.20; Wed, 25 Mar
+ 2026 14:21:21 +0000
+Received: from DU2PEPF00028D06.eurprd03.prod.outlook.com
+ (2603:10a6:10:4b4:cafe::39) by DUZPR01CA0214.outlook.office365.com
+ (2603:10a6:10:4b4::19) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9723.31 via Frontend Transport; Wed,
+ 25 Mar 2026 14:21:17 +0000
+X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 195.232.244.48)
+ smtp.mailfrom=vodafone.com; dkim=none (message not signed)
+ header.d=none;dmarc=pass action=none header.from=vodafone.com;
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 195.232.244.48 as permitted sender) receiver=protection.outlook.com;
+ client-ip=195.232.244.48; helo=VOXE03HW.internal.vodafone.com; pr=C
+Received: from VOXE03HW.internal.vodafone.com (195.232.244.48) by
+ DU2PEPF00028D06.mail.protection.outlook.com (10.167.242.166) with Microsoft
+ SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
+ 15.20.9723.19 via Frontend Transport; Wed, 25 Mar 2026 14:21:21 +0000
+Received: from appsmtp-north.internal.vodafone.com (145.230.101.21) by
+ VOXE03HW.internal.vodafone.com (195.232.244.48) with Microsoft SMTP Server id
+ 15.2.2562.37; Wed, 25 Mar 2026 15:21:20 +0100
+Received: from GBVLS-AS360 ([10.196.150.7]) by appsmtp-north.internal.vodafone.com with Microsoft SMTPSVC(10.0.17763.1697);
+ Wed, 25 Mar 2026 15:21:16 +0100
+Date: Wed, 25 Mar 2026 14:21:15 +0000
+From: Network Change
+Reply-To: Network Change
+To:
+Message-ID: <20012384.98430.1774448475992@GBVLS-AS360>
+Subject: Rescheduled 3rd Party Planned Works CRQ000001319054 Affecting I3
+ NET BV Services
+Content-Type: multipart/alternative;
+ boundary="----=_Part_98429_663222437.1774448475992"
+Return-Path: networkchangemanagement@vodafone.com
+X-OriginalArrivalTime: 25 Mar 2026 14:21:16.0707 (UTC) FILETIME=[A481F730:01DCBC62]
+X-EOPAttributedMessage: 1
+X-MS-TrafficTypeDiagnostic: DU2PEPF00028D06:EE_|AM9PR05MB8828:EE_|QB1PEPF00004E0C:EE_|MW4PR17MB5715:EE_|CH3PR17MB6987:EE_
+X-MS-Office365-Filtering-Correlation-Id: 62a244e1-27a0-48f4-c160-08de8a79ccfc
+X-MS-Exchange-SenderADCheck: 1
+X-MS-Exchange-AntiSpam-Relay: 0
+X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230040|82310400026|1800799024|376014|36860700016|8096899003|18002099003|56012099003;
+X-Microsoft-Antispam-Message-Info-Original: kufZtf73CjYfkADRJqx/eEkUwZZNIf1Q42wj7TB7wsDfmTKu138TTEm4Lt5rFSvKrdUoGcE/0oBwmdyC7lZ475G55Ax/8NLaZMXR/kULdSXymHzyMgqtHOKruhsG3ky72Z0SDF+3GQ4//6FTJZ42ZDeTNqVs1RIr7UeIEQcxL3nB8WfGbErS0LK6TPF7CraAhTlv7JiNkyr8QdoUKVFDcBjfXRAPZl+Vhr3VPlF5BjwMusPV4Pk8dUjI7mnbO8lDneXMnKh/UmBLsMJpcy7W+v/A9uqQUlPKQTmz3WotyR4axC6o8k1F1/5J+gNMUvHizvnV1jli9hKd/QgvpmYZzLkSRRzivTvnVirbNqcwDKloEjlM8/Rtm0mp4p7w2DmDkjGdqcLT+TPX7rVYyz28imgduTt9qCttLGCI/eGbVlM/wgQ7DxQz+PQH7WiQj9CuDkUM2fPJAqw8cJpoJTgF4M05DWj3lSOGkV3Sb9qUtEhI4BeNBDN6PRQtI1rsssz6vvi2zqPT/jrRxYOACU8r8LJxAbWBHqvNt6cQeRm6qSiM1MyKUbSRClmr+BOMnAJKs27uL6bKEOT1FQJkgF8azh9T7xGoPADE5faIRW86Ipxo7at/hIXGMiGmJLEh/I7RQkHwqJkVdAo01O2GEXKhtzeVBQQVP+HnPS6qr7q9ILJMwwr//TEZuLYo0C6yfegvVN7db+4/jPkD5GWS3Y5X3AFRTvBly73qZMo4+CCKbtZ1KbESd4HHP0AygSWBr+iuJ8k3t2wahds9bjbowpXtGQ==
+X-Forefront-Antispam-Report-Untrusted: CIP:195.232.244.48;CTRY:IT;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VOXE03HW.internal.vodafone.com;PTR:msedge3.vodafone.com;CAT:NONE;SFS:(13230040)(82310400026)(1800799024)(376014)(36860700016)(8096899003)(18002099003)(56012099003);DIR:OUT;SFP:1101;
+X-MS-Exchange-AntiSpam-MessageData-Original-ChunkCount: 1
+X-MS-Exchange-AntiSpam-MessageData-Original-0: 9AZAd7vmvRv7Xhc1rvDX3fEnBgBCAXePIsKlN15WkKJ27hVQcbC2HAqFinzi6zubPmYJSBRhKo+tScWBEhA+6dZyCGZy35k09LvK5+d2OtwBy/5KVji09GBAZhytI7HONY3o/y3gaLEBSsOTfXkZXrVBltXM07ca6uiDdX0xZweobZIpjjqhQ9SvYutP5JJMghoD6t3//0EahO6y36dypiHUYDmAPbGbzna+v5R/gHjv7v2U31lFl+zepLrtt+1I/Ly/gBcoVd7JsuXXuhDM1rI+F+DIrYCPXC6TpXa1CloqtTJ/uhLWEeOGdQb1pRA5S0b5ypCGXihW9JOQ8mJaJq+Zr+jzNotLjosoonvfyhY29KnZ/LxhUkN6KVZpj2t1Y6HswT2GSdbmeKFZ9/eJLkK33pxjiGO/kDc1dmFDDAykZH3TGbjrfiLMyqHMKmdi
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9PR05MB8828
+X-MS-Exchange-Organization-ExpirationStartTime: 25 Mar 2026 14:21:26.7981
+ (UTC)
+X-MS-Exchange-Organization-ExpirationStartTimeReason: OriginalSubmit
+X-MS-Exchange-Organization-ExpirationInterval: 1:00:00:00.0000000
+X-MS-Exchange-Organization-ExpirationIntervalReason: OriginalSubmit
+X-MS-Exchange-Organization-Network-Message-Id: 62a244e1-27a0-48f4-c160-08de8a79ccfc
+X-EOPTenantAttributedMessage: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1:0
+X-MS-Exchange-Organization-MessageDirectionality: Incoming
+X-MS-Exchange-Transport-CrossTenantHeadersStripped: QB1PEPF00004E0C.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Transport-CrossTenantHeadersPromoted: QB1PEPF00004E0C.CANPRD01.PROD.OUTLOOK.COM
+X-MS-PublicTrafficType: Email
+X-MS-Exchange-Organization-AuthSource: QB1PEPF00004E0C.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Organization-AuthAs: Anonymous
+X-MS-Office365-Filtering-Correlation-Id-Prvs: 103f3f26-9e5e-4fe6-f693-08de8a79c99c
+X-MS-Exchange-AtpMessageProperties: SA|SL
+X-MS-Exchange-Organization-SCL: 1
+X-Microsoft-Antispam: BCL:2;ARA:13230040|704161411799003|12012899012|3072899012|2092899012|35042699022|8096899003|55112099003|57112099003|13003099007|19002099003|16102099003|18002099003;
+X-Forefront-Antispam-Report: CIP:2a01:111:f403:c201::1;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM0PR83CU005.outbound.protection.outlook.com;PTR:mail-westeuropeazlp170100001.outbound.protection.outlook.com;CAT:NONE;SFS:(13230040)(704161411799003)(12012899012)(3072899012)(2092899012)(35042699022)(8096899003)(55112099003)(57112099003)(13003099007)(19002099003)(16102099003)(18002099003);DIR:INB;
+X-Auto-Response-Suppress: DR, OOF, AutoReply
+X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Mar 2026 14:21:26.5595
+ (UTC)
+X-MS-Exchange-CrossTenant-Network-Message-Id: 62a244e1-27a0-48f4-c160-08de8a79ccfc
+X-MS-Exchange-CrossTenant-Id: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1
+X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=68283f3b-8487-4c86-adb3-a5228f18b893;Ip=[195.232.244.48];Helo=[VOXE03HW.internal.vodafone.com]
+X-MS-Exchange-CrossTenant-AuthSource: QB1PEPF00004E0C.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-CrossTenant-AuthAs: Anonymous
+X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR17MB5715
+X-MS-Exchange-Transport-EndToEndLatency: 00:00:03.9879921
+X-MS-Exchange-Processed-By-BccFoldering: 15.20.9723.025
+X-Microsoft-Antispam-Mailbox-Delivery:
+ ucf:0;jmr:0;auth:0;dest:I;ENG:(910005)(944490095)(944506478)(944626604)(920097)(930201)(20251009189)(140003);
+X-Microsoft-Antispam-Message-Info:
+ =?utf-8?B?dFN1eUFkbmpRZS92TnVtS0xhcC9TLzF5Q0lqUzBRYnBCOEo1cGhmcWRvWGxj?=
+ =?utf-8?B?dXN5L044QytpdGxqZnlGSHk4ZmtpRENJSUZqQ1ZSWWRmMCsvc2Rnekx0bnVz?=
+ =?utf-8?B?TEs3Z2xkSGwrZTExWElLRHBVcGx4RFZ5VXI4cFZqNi9jcitaUHZuQTF4MXYy?=
+ =?utf-8?B?bjdVMEViSHNTMDY3YzJ5NElaU21qaXFzZEIwNzdTZ0xHRU5ZT0tOaXEyNHNZ?=
+ =?utf-8?B?ZUZuVlNYa3JKSzhBTGRTVW1jM2VucGo5emYrWk9oY3liU1UrWVBrZUNHN3VS?=
+ =?utf-8?B?cmx1U2hEcDV6VkI4eG84MXp0d1BUc1hxYndOZTcwWE55bmZ4aDh1aTBndFdn?=
+ =?utf-8?B?QXNkWmJHMnd2eUxiMVk1T2FuQkZHbWlHem1pVFlUYWgrenFtbENTZzdKaVRZ?=
+ =?utf-8?B?c0txOEFud0RPbDB6SDBBQlVlNFY2bDhQUFNYa0U1VW1MbWFLbHcxWGh1b05m?=
+ =?utf-8?B?MVIxcE9jSlg1YXFCTVlmY0RtTEZZMnZZaUkyaFltaEZBaE5uVVZGUjVtN0Zz?=
+ =?utf-8?B?d0VMNHZmaDFyRnZyWktpYk8xMExkSVVrNE5KSWRvaFZSYzEwb1VmOUQyZ0U4?=
+ =?utf-8?B?L2paNk9lbXFZSlptcUFTTWtvNkE5RmNTcXV5WW9Nb3NkOVZYeEM3aksvTUc5?=
+ =?utf-8?B?dHBrWTBVTFJMSFNFTzhwcE1ZOW9jZG1RSGtQOW5xMkhxbjNwOTJ2UWZieHlF?=
+ =?utf-8?B?N0o0Qm9YZUNIVjV1cU9IYmJhZVM2ZnBVZHE1TjR6N1U4dlhhcmQxeGU3dTZ6?=
+ =?utf-8?B?SE9ZVGlMbDAxbGY3ei9kcXQwS2s5WVhKTWxkSkxyd1pHa0d4M0JjeEV5c1Bt?=
+ =?utf-8?B?bGtqaVlpc3VkWStIc2cyM3F3UW1IZGY0V3lHRnlmN29wODNpQW0wVTk4VkdD?=
+ =?utf-8?B?NDhVQ29RNHd5cHVCUjBaR2JoNm1HeVRDNitoYU5uUmpUYVNjbUNNNHI5MzFG?=
+ =?utf-8?B?djRyaXIxZURnZDFyZ05FN2FvVTJkMEV6aEsxcVRZRFc4NDk3Zy9xcDJoa0Vh?=
+ =?utf-8?B?Y3VyaFIxcm14TjZhOHAzYy96ZFZrVGlHazZMODBIa0QrelNlRXhNN0dvdFYw?=
+ =?utf-8?B?b2FaT2wvSkxLZWV1cGIzK3h6WngyYWdYUlc5VklHNjV5V2lFek9FNUpZMXFq?=
+ =?utf-8?B?Y2F0V3YwS0d4SUZQWjR4REIvcFB0Y2Vxb3pmVm5TU3BOTlRWb040aW1pNDJP?=
+ =?utf-8?B?aFp5aHQ5dWlwK0JlREdOZmlnK2lONmhCcmJLOTNlc0FsU3UrSVovSUNOM3p5?=
+ =?utf-8?B?SGNnb3dSSXFXVVdMSEx2Si9pMUNDUldDMElNdFBoSFZzbmpYc3ZwV24xWUxy?=
+ =?utf-8?B?MGluVEtJWWNGdGFMMEhQWGRTYXlBM3FLS3VuT2xWaVJ3OFBKdmpEVkFtS0wv?=
+ =?utf-8?B?SVFLYTBZT24wbUx5RVdwV3FxeU1JZWpNYlJhVFlvM05BT1A2U1FkbHQ5VlB0?=
+ =?utf-8?B?MjVLaUxweWNtenZkVzZFaFRjVzIrWWVzbEU5NGZhWkRkNlBYbkE2MklBYmsw?=
+ =?utf-8?B?dGQyOEFFQXRnTGVjY3AxUTRIYjc3YTQ4RkhqNWdPcm5pV1lqRjkrbkc0MDZj?=
+ =?utf-8?B?aFRNUGFyRzNrYlNINm84WTY4RXVyK1J3K0c0aW1OWUNTaVR3ZUdIbGZoRDlK?=
+ =?utf-8?B?S2RETDBTVDBsTzd6eEZsdVlTczRqcGtFZ3V6TUEwUDh6OEFMM3hXb0l3Ykxr?=
+ =?utf-8?B?MXB4bFJvejY1V1RyU0dEVE5yTUdUNGU3Uldxd1IyVUpCUFFrZm9wVEpERll2?=
+ =?utf-8?B?ZDJsQmhTT0E1YzkzSElrVXhZR0pFWWFqQnlUdHdwbTdNV1FnRHM5M2hlajFa?=
+ =?utf-8?B?WTFqTTFBQ2NDZGRsWHl5Y0RuUzdUckFDdy9TWUl1cjFMR01ja1lVUWpFV09V?=
+ =?utf-8?B?ckdET1ovT0hsVjdlMlUxOSt5R0piT1g2WGVDM0JXS0J4YW85bk5UelRDNkkr?=
+ =?utf-8?B?eUJtdytPc0VDMkRNdnphTkxoWmR0UXNxMlBBTXRCUTlnUlgxL0hEL3NUaFFY?=
+ =?utf-8?B?bmEyNWM5amdrbHU1WkJ4M0pKdU5DTG9abnRCanRDTkNZZWEvOFZuQU5LYmhF?=
+ =?utf-8?B?RUNUMitaV1ZIYm9PRGRjd2U5b01tc0lFbFBUSy81SHpobUtoVm5senBmSkxO?=
+ =?utf-8?B?d1NqakVSOTJQbE0zdDUvcE5sdlpqTjdaS0t1ZXlZTXIrYXJXdDY1aU14NVVR?=
+ =?utf-8?B?WjA1TlhFNmRQbnVBSVluV1gzSFF5cDN1eGt3eE4yNGFKNWJJaUlXbGkxaEtj?=
+ =?utf-8?B?dEd3c1Q3SUhMUUx4OUk1dGE3NVJzbm5oUUV2RDI0ZTk5RnQxWUp3OHZvRXdu?=
+ =?utf-8?B?Z0pZOC9hdmJncjVYUGMyN3FwQUdIeDFuYm4wTGZVTDdrZGxtODA4UHJXd3Fn?=
+ =?utf-8?B?cGhKOGtuQWJ0Zk9MOWtLbE5hUWhxRUQrUUxEN1drNkJVeUlnQ3VkSysrR2pz?=
+ =?utf-8?B?cE9JUG5WcVBLVzNJNkxpZ1g3MkE2ZUdKenh4dk5IVW5nVGFLOStjbmNwVDZS?=
+ =?utf-8?B?WlArWFBmRy9Yb215eHEyQ0xlbXlwUFVwaXo5ZGpBVUdGMjZGNit2QXJqcXkx?=
+ =?utf-8?B?ay9MM3cwZUlmNnQ5OFFsNHIyR2srRC82S0duVnNOSXpmNCtTazMwWmFZOURy?=
+ =?utf-8?B?RXJSYU5hRk5SaGgxaUl1N05PcUl6UkJIaW1PSEVrdkc4V090TGsvNEtJTnBE?=
+ =?utf-8?B?NkdZR1RHUkQrdFFzNlRoYktxSDU0em55OTdhMXZYNkdtVUZJUjYra25Malph?=
+ =?utf-8?B?M3ZqRUVhVlBZVjJNQU9TQUtpOHhVR29oNjdiVTh3WC9mdkoydkNuQ0pOSHJj?=
+ =?utf-8?B?aHUrdktuNk1ldS9kS0VSNUNVUHhHUXhodzhIc015UWU2OERDemlKSEU1MXRh?=
+ =?utf-8?B?T3JEV2FlNWV6ZnFiSjZOeFVJcGwvN2IxZnArWGJNLzZBVnBTRnIweWtwZFlE?=
+ =?utf-8?B?Ymp2c1JVY1AvYWp5K1NaSFhUdXQ5emh0UUlZQ2Z0Wkg3MThvV2pxWGpUK3c3?=
+ =?utf-8?B?MDIra0FTb2o3VnAyeXl4MmhYNDdDZGI0V3R6Y2ZoUUpaSW1UWGVGdm5INlB0?=
+ =?utf-8?B?bG9wYk5odzQ5TEpST1B2a05hRUtKSUI1WjJZSGdtRks5SFc4akxITnZINmI3?=
+ =?utf-8?B?YmNVV2F0SlNYbCtzMWlUZHAvZitLWXZMZjUwVlBxVmg4TndTcnZtT3hOdVBm?=
+ =?utf-8?B?amtqd2gzVU5GNVFEdVZxVVRHWnJtbHpsWnZTYnB0ajRRVThjSHpqL0o1dDJR?=
+ =?utf-8?B?aUhXWi9FLzBhYWlFMytaTWk3M2hMdzZSNE9RckJyTmNGQjY0RHBlSzB1bWhU?=
+ =?utf-8?B?LzgwbUl1TmlGOS8zTnltL3grRldwUklVeHVxNlVBSW43MXlGVFAvSVQ5NHRN?=
+ =?utf-8?B?RXVjWHZFSWE4a2FMdkhNRTUzYXlMdkVpNzM3TFozVEtrUWpIdFgybkhndlhF?=
+ =?utf-8?B?UTJkRmM5VzRlZkJWQmFZWm5rUWIwQnIwSmhEd2t1M1F3S1hFaTVRSHFJSXpZ?=
+ =?utf-8?B?UEZxSXpKU0NUeWJtV3NTVGszY3lSSEppYStaOUVhcStOeUNjRUhmZ2o5Zm5v?=
+ =?utf-8?B?ZmRnV0NRMnBPM2haZENNU1dkYUhDSWJTcWNLbERnSjRDL29veDhzNUMxeERa?=
+ =?utf-8?Q?JdAskYdh3+4Fw8myfKfW1ZqTuJ9I+eF0i?=
+MIME-Version: 1.0
+
+------=_Part_98429_663222437.1774448475992
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Vodafone UK - Technology Operations
+Planned Maintenance Notice
+
+
+Dear ACME CORP,
+
+Please be advised that the Planned Works have been rescheduled: CRQ00000131=
+9054
+
+Detailed Description of Works:
+Rescheduled 3rd Party Planned Works to perform cable repair work in their p=
+artner's network
+
+Original Scheduled Start/End Date & Outage Window:
+07/04/2026 00:00 to 13/04/2026 00:00 UTC
+
+New Scheduled Start/End Date & Outage Window:
+06/04/2026 00:00 to 13/04/2026 00:00 UTC
+
+Impact Assessment:
+Loss of service for complete window
+
+Contingency Date:
+NA
+
+Services Impacted:
+
+Services Affected Customer Service Impact Address Service Typ=
+e Service Model Customer Reference Node
+X0013337A ACME CORP Loss of Service SAINT DENIS RUE AMBROISE CR=
+OIZ,114,RUE AMBROISE CROIZAT,SAINT DENIS,,*FR >>> SINGAPORE PIONEER WALK 15=
+,15,PIONEER WALK,SINGAPORE,*SG 160510GLA / STM64 N/A N/A S=
+GPSGP004 <> FRASTD003
+
+
+
+Issues regarding circuit identification, please contact your Vodafone appoi=
+nted Service Manager/ Account Manager.
+
+The information given is what is held in our records and should have been p=
+assed to you when the service went live.
+Thanks
+Vodafone UK Fixed
+Change Management Analyst
+Change Management
+Email: networkchangemanagement@vodafone.com
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limited a=
+nd Hutchison 3G UK Limited and this email is sent on behalf of Vodafone Lim=
+ited and/or Hutchison 3G UK Limited. The message and any attachment(s) are =
+confidential, may be legally privileged and are intended solely for the att=
+ention of the addressee(s). If you are not the intended recipient or you h=
+ave received this email in error, please notify the sender immediately, del=
+ete it and any attachments from your system and do not copy, disclose or us=
+e its contents for any purpose. This transmission cannot be guaranteed to b=
+e secure or error-free. Any views or opinions expressed in this message are=
+ those of the author only.
+
+Vodafone Limited. Registered in England & Wales | Company no 01471587. Voda=
+fone House, The Connection, Newbury, Berkshire, RG14 2FN. Authorised & Regu=
+lated by the Financial Conduct Authority for consumer credit lending and in=
+surance distribution activity (Financial Services Register No. 712210).
+
+Hutchison 3G UK Limited. Registered in England and Wales | Company number 3=
+885486. Registered Office: 450 Longwater Avenue, Green Park, Reading, Berks=
+hire, RG2 6GF. Authorised & Regulated by the Financial Conduct Authority fo=
+r consumer credit (Financial Services Register No. 738979).
+
+VodafoneThree is a holding company of Vodafone Limited and Hutchison 3G UK =
+Limited, see www.VodafoneThree.com to learn =
+more.
+
+------=_Part_98429_663222437.1774448475992
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+
+
+
+
+Vodafone UK - Technology Operations=
+span>
+Planned Maintenance Notice=
+
+
+Dear ACME CORP,
+
+Please be advised that the Planned Works have been rescheduled: CRQ00000131=
+9054
+
+Detailed Description of Works:
+Rescheduled 3rd Party Planned Works to perform cable repair work in their p=
+artner's network
+
+
+Original Scheduled Start/End Date & Outage Window:
+07/04/2026 00:00 to 13/04/2026 00:00 UTC
+
+New Scheduled Start/End Date & Outage Window:
+06/04/2026 00:00 to 13/04/2026 00:00 UTC
+
+Impact Assessment:
+Loss of service for complete window
+
+Contingency Date:
+NA
+
+Services Impacted:
+
+
+
+
+| Services Affected |
+Customer |
+Service Impact |
+Address |
+Service Type |
+Service Model |
+Customer Reference |
+Node |
+
+
+| X0013337A |
+ACME CORP |
+Loss of Service |
+SAINT DENIS RUE AMBROISE CROIZ,114,RUE AM=
+BROISE CROIZAT,SAINT DENIS,,*FR >>> SINGAPORE PIONEER WALK 15,15,P=
+IONEER WALK,SINGAPORE,*SG |
+160510GLA / STM64 |
+N/A |
+N/A |
+SGPSGP004 <> FRASTD003 |
+
+
+
+
+
+
+Issues regarding circuit identification, please contact your Vodafone appoi=
+nted Service Manager/ Account Manager.
+
+
+The information given is what is held in our records and should have been p=
+assed to you when the service went live.
+
+Thanks
+
+Vodafone UK Fixed
+Change Management Analyst
+Change Management
+Email: networkchangemanagement@vodafone.com
+
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limite=
+d and Hutchison 3G UK Limited and this email is sent on behalf of Vodafone =
+Limited and/or Hutchison 3G UK Limited. The message and any attachment(s) a=
+re confidential, may be legally
+ privileged and are intended solely for the attention of the addressee(s).&=
+nbsp; If you are not the intended recipient or you have received this email=
+ in error, please notify the sender immediately, delete it and any attachme=
+nts from your system and do not copy,
+ disclose or use its contents for any purpose. This transmission cannot be =
+guaranteed to be secure or error-free. Any views or opinions expressed in t=
+his message are those of the author only.
+Vodafone Limited. Registered in England & Wales | C=
+ompany no 01471587. Vodafone House, The Connection, Newbury, Berkshire, RG1=
+4 2FN. Authorised & Regulated by the Financial Conduct Authority for co=
+nsumer credit lending and insurance distribution
+ activity (Financial Services Register No. 712210).
+Hutchison 3G UK Limited. Registered in England and Wale=
+s | Company number 3885486. Registered Office: 450 Longwater Avenue, Green =
+Park, Reading, Berkshire, RG2 6GF. Authorised & Regulated by the Financ=
+ial Conduct Authority for consumer credit
+ (Financial Services Register No. 738979).
+VodafoneThree is a holding company of Vodafone Limited =
+and Hutchison 3G UK Limited, see
+www.VodafoneThree.com to lear=
+n more.
+
+
+
+------=_Part_98429_663222437.1774448475992--
diff --git a/tests/unit/data/vodafone/vodafone2_result.json b/tests/unit/data/vodafone/vodafone2_result.json
new file mode 100644
index 00000000..b155076d
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone2_result.json
@@ -0,0 +1,16 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1776038400,
+ "maintenance_id": "CRQ000001319054",
+ "start": 1775433600,
+ "status": "RE-SCHEDULED",
+ "summary": "Rescheduled 3rd Party Planned Works to perform cable repair work in their partner's network"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone2_result_combined.json b/tests/unit/data/vodafone/vodafone2_result_combined.json
new file mode 100644
index 00000000..e929fca0
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone2_result_combined.json
@@ -0,0 +1,21 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1776038400,
+ "maintenance_id": "CRQ000001319054",
+ "organizer": "networkchangemanagement@vodafone.com",
+ "provider": "vodafone",
+ "sequence": 1,
+ "stamp": 1774448475,
+ "start": 1775433600,
+ "status": "RE-SCHEDULED",
+ "summary": "Rescheduled 3rd Party Planned Works to perform cable repair work in their partner's network",
+ "uid": "0"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone3.eml b/tests/unit/data/vodafone/vodafone3.eml
new file mode 100644
index 00000000..82d35a9b
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone3.eml
@@ -0,0 +1,411 @@
+Received: from MN2PR17MB3981.namprd17.prod.outlook.com (2603:10b6:208:209::7)
+ by MW4PR17MB4604.namprd17.prod.outlook.com with HTTPS; Wed, 11 Feb 2026
+ 14:15:50 +0000
+ARC-Seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass;
+ b=Kp5cSkrMQCYNflt633pmLlbSZxU4pLA1dg+oNwjkYXE/fXFeRtIlxCfJVnR5k0KrSslpPAYWO+JPvqVGKjMv0JItTyYXfv5qrhjdumXPlM5/pm/K9jfqWuVtealDXM9jjqQU2PZK+TdMxrrJ333M4i0RcJoJCn1Wk9iZWv2Ys6n5Edggi1p4UeZF1sE09oW25pUizHRTOyyRWeXxNxSBzOCvn4HrapO25fVEfSNaBNliNYPK1zppKjuFB4UmLOyP3DC4kqnbREWrkYCTBKND57FUiTTmV7ehn/3Wjf5z/DH7iDw/dcQJuuyV3a1fcHJ0oNNTQ3QQXLNO3xhBbWgqwA==
+ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=1inllJbX9ipb4kNfQSByA4376tCwhXaR73dlmElngcg=;
+ b=XV+GM/mWV9cSI+tulCnJZZpRV1ULnYqC1+GfEaTrjk4NpFG0Q/4Bi2tXGC4Y0BjEaehxiwWdvFMgRN1H7gDUMnRWkjsLy/omYZyAn6dK6WKcLXyBgKU7No7XqE9u8UjGkikbc65yCMzd+CF1Qe7jcT/caF2yAEd3kjjK+fZEDBHF4HqvGV2Sd8aCMe5wp8nmgXwuEWfeaQsBFeCBTH7D68QieddSUyb2eVLUNrd/XbQx4+xuT7OdOe+E7uxtCjhRzXZ/GvVJ9YoC72VufggZ7XEGECakMi8Lk99AmDWw/9vCZW45nkv7zEqumdQ49PaX80UtN7my/d4udiCs79belw==
+ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is
+ 2a01:111:f403:c202::7) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=pass (signature was verified) header.d=vodafone.com; arc=pass (0 oda=1
+ ltdi=1 spf=[1,1,smtp.mailfrom=vodafone.com]
+ dmarc=[1,1,header.from=vodafone.com])
+Received: from YT2PR01CA0012.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:b01:38::17)
+ by MN2PR17MB3981.namprd17.prod.outlook.com (2603:10b6:208:209::7) with
+ Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9611.10; Wed, 11 Feb
+ 2026 14:15:47 +0000
+Received: from YT2PEPF000001C9.CANPRD01.PROD.OUTLOOK.COM
+ (2603:10b6:b01:38:cafe::80) by YT2PR01CA0012.outlook.office365.com
+ (2603:10b6:b01:38::17) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9611.8 via Frontend Transport; Wed,
+ 11 Feb 2026 14:15:41 +0000
+Authentication-Results: spf=pass (sender IP is 2a01:111:f403:c202::7)
+ smtp.mailfrom=vodafone.com; dkim=pass (signature was verified)
+ header.d=vodafone.com;dmarc=pass action=none
+ header.from=vodafone.com;compauth=pass reason=100
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 2a01:111:f403:c202::7 as permitted sender) receiver=protection.outlook.com;
+ client-ip=2a01:111:f403:c202::7;
+ helo=GVXPR05CU001.outbound.protection.outlook.com; pr=C
+Received: from GVXPR05CU001.outbound.protection.outlook.com
+ (2a01:111:f403:c202::7) by YT2PEPF000001C9.mail.protection.outlook.com
+ (2603:10b6:b08::115) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9611.8 via Frontend Transport; Wed,
+ 11 Feb 2026 14:15:45 +0000
+ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;
+ b=nobXqVq6CtVtHfGagvDJtBaRZTmr80UCadsL3AUkqTx8ebD/ovsCVL98XPhVwkBB02CZg9mZpVufuZwRK6JP4mGTCnrv9kpNj7MIoDmIGNPOL/X1zQpXQqFORkWzR39eHEopJXnUA/JHEzZWXz2I62hx+zUGc++uvAXEys2BOKuV3qvDIwCzXdDFDy1o1XdRUA3Y/K6BiKXFvNANP1PHLPSbFeweWReP64xwD4BXSgtL0TggwdkxE47uXXpMe8VqT9fNRWxGrg2qDjDebJLH46aVc7SeSjPyW51CgM9eKm5oppqY+U4UxKmfznh8bv4KwCj6uJ387HZarhvhkem+zw==
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
+ s=arcselector10001;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
+ bh=1inllJbX9ipb4kNfQSByA4376tCwhXaR73dlmElngcg=;
+ b=KWM++ICB1EZk76ATBJikcKXpQHFs9e6PdNK0uEIPc9VQspLj0x2BdGlK2TMAfng9/XWIvlDxBVwHMS7tT1Xh1gkUYT6WrwK72g2B0yUFvq2pB4Z4syVETzi5xLRTShzLklzZA0lyXEte+ecDwoTYzZlY2WHKlNA2OaGG8DVLHrYe6lyz3Szu0c7/siMv6qNBYDe7SwamUXFyAk0epC6r5bajWm61zv3bmmn2Kc+XP6opT4fDoyJBqk1O8Z0dc3wt9hdZXAlFcOzPyk8bNlxO2CkLjpnPqoa5RLHk1y2kDZjOZghV7osL6OeK5BXM+/ZNfdWkakn1rFZ8Pu29qw1wIQ==
+ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is
+ 195.232.244.51) smtp.rcpttodomain=example.com smtp.mailfrom=vodafone.com;
+ dmarc=pass (p=reject sp=none pct=100) action=none header.from=vodafone.com;
+ dkim=none (message not signed); arc=none (0)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.com;
+ s=selector2;
+ h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
+ bh=1inllJbX9ipb4kNfQSByA4376tCwhXaR73dlmElngcg=;
+ b=GtRQgfhFxh6SWey0K4qxOETuPInFjAg9xc12r1vCawyVqHGOMxF+J5gWMcL1SUiJM3wa7/Khdz9EAZuyEcDmjh6nnj9wk1FtUPlgmZ3SW4QyWtLmElOIUeoxHfjxUpWgP7TKtSY0BaJIX4JW+soofFEcIiWms+eg1F51Vj6QngJYJ6GjyNBQo8hR/7IkoURnzE/Yg6Z9JoXQzgu+BMQmlBjPIIb3AxGFS0BMBUbIIH/fSxofg+gdCPNxNMWZOTaaLlR3UB/iANS/U6ylVtbcCAI/Anbmjy6Wbvs54S5WTGRiwYU1C/sM1hA2wuWnqoMUi+8eXUGoii8I9tFfUUbl7Q==
+Received: from AM0PR02CA0154.eurprd02.prod.outlook.com (2603:10a6:20b:28d::21)
+ by PA1PR05MB11788.eurprd05.prod.outlook.com (2603:10a6:102:4ee::6) with
+ Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9587.19; Wed, 11 Feb
+ 2026 14:15:38 +0000
+Received: from AM3PEPF0000A793.eurprd04.prod.outlook.com
+ (2603:10a6:20b:28d:cafe::3) by AM0PR02CA0154.outlook.office365.com
+ (2603:10a6:20b:28d::21) with Microsoft SMTP Server (version=TLS1_3,
+ cipher=TLS_AES_256_GCM_SHA384) id 15.20.9611.8 via Frontend Transport; Wed,
+ 11 Feb 2026 14:15:37 +0000
+X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 195.232.244.51)
+ smtp.mailfrom=vodafone.com; dkim=none (message not signed)
+ header.d=none;dmarc=pass action=none header.from=vodafone.com;
+Received-SPF: Pass (protection.outlook.com: domain of vodafone.com designates
+ 195.232.244.51 as permitted sender) receiver=protection.outlook.com;
+ client-ip=195.232.244.51; helo=VOXE06HW.internal.vodafone.com; pr=C
+Received: from VOXE06HW.internal.vodafone.com (195.232.244.51) by
+ AM3PEPF0000A793.mail.protection.outlook.com (10.167.16.122) with Microsoft
+ SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
+ 15.20.9611.8 via Frontend Transport; Wed, 11 Feb 2026 14:15:38 +0000
+Received: from appsmtp-north.internal.vodafone.com (145.230.101.22) by
+ VOXE06HW.internal.vodafone.com (195.232.244.51) with Microsoft SMTP Server id
+ 15.2.2562.35; Wed, 11 Feb 2026 15:15:36 +0100
+Received: from GBVLS-AS360 ([10.196.150.7]) by appsmtp-north.internal.vodafone.com with Microsoft SMTPSVC(10.0.14393.4169);
+ Wed, 11 Feb 2026 15:15:25 +0100
+Date: Wed, 11 Feb 2026 14:15:21 +0000
+From: Network Change
+Reply-To: Network Change
+To:
+Message-ID: <1033915984.68711.1770819322004@GBVLS-AS360>
+Subject: Completed Vodafone E2E Service Change Management Planned Works
+ CRQ000001312927 Affecting ACME CORP Services
+Content-Type: multipart/alternative;
+ boundary="----=_Part_68710_325875922.1770819322004"
+Return-Path: networkchangemanagement@vodafone.com
+X-OriginalArrivalTime: 11 Feb 2026 14:15:25.0429 (UTC) FILETIME=[DDC7B250:01DC9B60]
+X-EOPAttributedMessage: 1
+X-MS-TrafficTypeDiagnostic: AM3PEPF0000A793:EE_|PA1PR05MB11788:EE_|YT2PEPF000001C9:EE_|MN2PR17MB3981:EE_|MW4PR17MB4604:EE_
+X-MS-Office365-Filtering-Correlation-Id: c07a01b2-f716-475e-26dc-08de69780ca8
+X-MS-Exchange-SenderADCheck: 1
+X-MS-Exchange-AntiSpam-Relay: 0
+X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230040|82310400026|36860700013|1800799024|376014|8096899003;
+X-Microsoft-Antispam-Message-Info-Original: =?us-ascii?Q?Z3z+EItsYcORCahzuiiKxpZhZrF4Oyb86G+KnKUau4NGKKt7r52LV2L68nC2?=
+ =?us-ascii?Q?3cf0e/6C+LZ1zjkrupBO4IYS8fgwkDAJ60k1ZsP3IIcxsqQORzkXCtl4tTIO?=
+ =?us-ascii?Q?zt/sT0jCNUBk+bR0OYYLKGkEXLLWd2J4L8/d+WnYYjSYPBGLdiQGGL6FvTza?=
+ =?us-ascii?Q?3Lc/EDur1a/1XxPVOhDwEjUA/LeCVY72wknF6TtMsoPGOfzKwbkh/z634hH5?=
+ =?us-ascii?Q?jqPZ5DBPPrvZvBxDwU29x+aezvhyBnop+fXfdbcGgsOQQnvOmy2A/sA2cRKe?=
+ =?us-ascii?Q?2vdwlgTtqAt5Oi26VoUQATQfHihcQk1Bsb9vMRrvsHJEP2xcBnlwVcNMpMGu?=
+ =?us-ascii?Q?fZNakKGHVmE43f5aFpygJxSZ3me+VY2SpsXcZVvXIpR5sBtSkOCRsJ0tOGJn?=
+ =?us-ascii?Q?x0PE7MpnH2O5FNDpuWa2uDJmNu3R/T78SbiwjTb+SeI7ceOMj8gJNl0wkhin?=
+ =?us-ascii?Q?ouK7w1OsZqZw/FVMsSfFV5a5az13It2J2ExkxkXfAa0Od4xoy6sz8fZZHiXp?=
+ =?us-ascii?Q?kfzz+Xdc/YcNc7/UN4zz0vaPenIqsoi0aBlT6bcFdk8QBAoy6ODfVFESOcAf?=
+ =?us-ascii?Q?60mdRNzxQJMTZzg252eP0QLc1sFhANLPH1JW1lsw3gFHKeAcCdT8jn+6fqZp?=
+ =?us-ascii?Q?OfTee/3Xop1MoF5Y7fCISn6DpNRSF3L3jq2Vcm/ItuYJPviaKXIVgXZD5rqi?=
+ =?us-ascii?Q?bIsvZkHx6CrHYO5xGhmwc4s6J9zhkdqmCCYITzevy1gAZ0UHK1trQr5FECLx?=
+ =?us-ascii?Q?HCfrthbdF86G5qJ1+u/OkOtBkqJfPo3/Eq0L6P02nllTywWHF/03oISnrGa6?=
+ =?us-ascii?Q?eyMDhBV6/2bJGskveD5a8bpSf+1BqAXyiYqiNH4Wa0Rv0HjbsY98He4pELyG?=
+ =?us-ascii?Q?hpLRiOUurX2pM4ViPM4YW+tcCNj+gL8c7zBTPcKX/onTLnUTophN2UHTXqQn?=
+ =?us-ascii?Q?DtFJpVoXQwWtksbNhEum5Hn+bZmq7xGqr+mxkHaJIQhb1SdC2JdZCkhiw/mn?=
+ =?us-ascii?Q?nCwq4HZJ7kEEQafDa53/HUSfJGA9vi5hzoKD5cx+a9lELfKmpLo87VwUoKiW?=
+ =?us-ascii?Q?MgfCY8hPDPHMOOLRkeE/ZrPvYc/RRh4ZuUQJJfszqbWT9IQ825bZb4zsLwxu?=
+ =?us-ascii?Q?h2eq6+uhJmGvgvJJIfAXbV7MZsHJN3faC5V/anajj4vfEcJb1DxxaHwG1UHZ?=
+ =?us-ascii?Q?spTQ2LwIRcir9X+Vpn42tcRJjLcEVgSiyF+BvGbRGeoyboTFNcfOjnHrvfxk?=
+ =?us-ascii?Q?fhkY+zn3shoGwVtWf2eLFXaV3cGdufe2wt4+t980aoF+LjsPsF6+08w+veD2?=
+ =?us-ascii?Q?SbnJRt//RxmoTQltuTlq4/l3dAGcS4JXgCDaCTKcQmU4tkJpwg9+N40iFrye?=
+ =?us-ascii?Q?vHDIlLcQv1qlc3sl3Lj4oNaTKaejxidO5Ah9cK7b71XcrXDABIl2OHwd45eu?=
+ =?us-ascii?Q?v4klFK2aDlRlw+WDbVNhRcFGYC8S8yYOVHcSD71X5UUCPjiWO4rR9BkBy2OZ?=
+ =?us-ascii?Q?eHm5GY/FpcBi230cSuhJwh3iF6nqYEvu8a6b9Rp5REvvKuMQMgzzZHYOyDEr?=
+ =?us-ascii?Q?X5A4cQ37QguHd8sGijCl9dFHmIZAz1ye3vZxkf8At1YdqJRFDVtcJ9e6l6i7?=
+ =?us-ascii?Q?4LCHDQ17sbIsCO4iH2i18KzOJZmDk3NgdHctSIjnhpa/aBb7RbYqKsnisI0F?=
+ =?us-ascii?Q?iN51+A=3D=3D?=
+X-Forefront-Antispam-Report-Untrusted: CIP:195.232.244.51;CTRY:IT;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VOXE06HW.internal.vodafone.com;PTR:msedge6.vodafone.com;CAT:NONE;SFS:(13230040)(82310400026)(36860700013)(1800799024)(376014)(8096899003);DIR:OUT;SFP:1101;
+X-MS-Exchange-AntiSpam-MessageData-Original-ChunkCount: 1
+X-MS-Exchange-AntiSpam-MessageData-Original-0: j8ieTuIN0M1mKwad07D25vOY+ln0LnBJCkVXpKLATdWjQGt7E4lSPWMnCJz3NK8RrLn32Yu6sN7T/CWA1nib/33sEYt4k2vy0ZKvJrI06WFLHEBTY8PP4ULqhm26gMif2NuklXFCrCzlCXg1B7jPuPCvNm0WK+KZdgMme8WEsjzP/ofCFIQ1zQkE/fx3YN0oMtV+ENGJct1jGKvWW/jYQ0G0V5iGpxWqb9L/A6///hv6glL0MtyaMpoVUWeGgK19LFm5LaUqcAfnwdcq4tl1vTXYnJ3bN6Ntxfnnk6Fgu1FknySfGsUkRE2Ae1/sRdh6P9xI4HWepZgaXl0on4Pa6m5aM5er9mfTBLtJ0KnCXmGqfqlYP84eVoruWN8w62i3q4oy0lUWP7esdgO2eqwxn1xSSJmBGpuVoRnv3chDL8l2Io/UFh96rnozHRD2KKpZ
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA1PR05MB11788
+X-MS-Exchange-Organization-ExpirationStartTime: 11 Feb 2026 14:15:46.2527
+ (UTC)
+X-MS-Exchange-Organization-ExpirationStartTimeReason: OriginalSubmit
+X-MS-Exchange-Organization-ExpirationInterval: 1:00:00:00.0000000
+X-MS-Exchange-Organization-ExpirationIntervalReason: OriginalSubmit
+X-MS-Exchange-Organization-Network-Message-Id: c07a01b2-f716-475e-26dc-08de69780ca8
+X-EOPTenantAttributedMessage: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1:0
+X-MS-Exchange-Organization-MessageDirectionality: Incoming
+X-MS-Exchange-Transport-CrossTenantHeadersStripped: YT2PEPF000001C9.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Transport-CrossTenantHeadersPromoted: YT2PEPF000001C9.CANPRD01.PROD.OUTLOOK.COM
+X-MS-PublicTrafficType: Email
+X-MS-Exchange-Organization-AuthSource: YT2PEPF000001C9.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-Organization-AuthAs: Anonymous
+X-MS-Office365-Filtering-Correlation-Id-Prvs: 114f63ef-a0c5-4131-1a8d-08de697807f8
+X-MS-Exchange-AtpMessageProperties: SA|SL
+X-MS-Exchange-Organization-SCL: 1
+X-Microsoft-Antispam: BCL:2;ARA:13230040|35042699022|3072899012|12012899012|2092899012|13003099007|8096899003;
+X-Forefront-Antispam-Report: CIP:2a01:111:f403:c202::7;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:GVXPR05CU001.outbound.protection.outlook.com;PTR:mail-swedencentralazlp170130007.outbound.protection.outlook.com;CAT:NONE;SFS:(13230040)(35042699022)(3072899012)(12012899012)(2092899012)(13003099007)(8096899003);DIR:INB;
+X-Auto-Response-Suppress: DR, OOF, AutoReply
+X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Feb 2026 14:15:45.9655
+ (UTC)
+X-MS-Exchange-CrossTenant-Network-Message-Id: c07a01b2-f716-475e-26dc-08de69780ca8
+X-MS-Exchange-CrossTenant-Id: e01bd386-fa51-4210-a2a4-29e5ab6f7ab1
+X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=68283f3b-8487-4c86-adb3-a5228f18b893;Ip=[195.232.244.51];Helo=[VOXE06HW.internal.vodafone.com]
+X-MS-Exchange-CrossTenant-AuthSource: YT2PEPF000001C9.CANPRD01.PROD.OUTLOOK.COM
+X-MS-Exchange-CrossTenant-AuthAs: Anonymous
+X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
+X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR17MB3981
+X-MS-Exchange-Transport-EndToEndLatency: 00:00:04.7100274
+X-MS-Exchange-Processed-By-BccFoldering: 15.20.9564.000
+X-Microsoft-Antispam-Mailbox-Delivery:
+ ucf:1;jmr:0;auth:0;dest:C;OFR:CustomRules;ENG:(910005)(944490095)(944506478)(944626604)(920097)(930201)(20251009178)(140003)(1420198);
+X-Microsoft-Antispam-Message-Info:
+ =?us-ascii?Q?nk70Lgj5/D2auooJHHj/o4plK1uG6clowhdFK4VTRJGu+wCJ+n1Dk7xLVQAe?=
+ =?us-ascii?Q?ZopFhjvZg9g+9lv+ZOWTGSKQ4ZgcWlkAUzdrS9vfLPp913qqyy12jpQ628Ne?=
+ =?us-ascii?Q?5p6SrhiQV/37hXo0hdDpu8/e3bR8E5sQzWn+Aq/I4gfDizMMEvlST8bYNn20?=
+ =?us-ascii?Q?VjpznS90lFPTgg6kArGo2Y5QIGGknYUNX78yhrer8rB9nB/fr8YbD9o8pz1D?=
+ =?us-ascii?Q?yyyV38Ud+fnLYy+/pbtDRit8lOxhrJG1YjBP636QZTcYOSm+98egQ4C8tFwz?=
+ =?us-ascii?Q?8hyUGy8p9J4q2zsOAoMfyy3O1C62zkOtB002sZquS0ShSyf9LIREGEPf4Cbb?=
+ =?us-ascii?Q?vFaCBhRj2hTZkVL2sPUdAroKvneCIzH7j0sz/CCKDRIUDenADO2v4+rPJnm9?=
+ =?us-ascii?Q?fvvBg+N4q4I7y7SHiRDuaRNdm/Cli60tRadOUbEyGtjkABWN9BqbqDEIabS2?=
+ =?us-ascii?Q?/zudMVQAb+iSmoRHXMsZbQ2vEuefZBA99kj+dtI3XR+K28BKzi++KSEXllgZ?=
+ =?us-ascii?Q?/llWtNafKlNyyeqg1B36tlwBcgsAX16qVd2e3xNAZS9woHndGC1RVWGg7nn2?=
+ =?us-ascii?Q?kTGB4n+vxlrBdFEQET/7ygbwiuLrX9YSzv6/UEoH2CzyEghbhxGB5OTN8BSx?=
+ =?us-ascii?Q?cEZc5E82YJylM85N6VQklNKlOkGbDK0AtEzMKLP7tzGRBZmezTdY8ZMwcIP4?=
+ =?us-ascii?Q?7/htUgY8HY81tE8oSZxDaOFtxdukt8cy8GPgVvS7JGdQNB7w2JrvpBl2uKGI?=
+ =?us-ascii?Q?aAzZ/TL3zl2H4keQj1kNUs6TmgV4eHyYg42oIyp7MxbnZmhrxu76djs9SX6X?=
+ =?us-ascii?Q?fPXJZOf40/l25SWb3kOIPzjFF3I//qfEAintqzfzQhskza+QEPnG+DiZ3ah3?=
+ =?us-ascii?Q?UnKW9WpkHBLtf+WVly7IdYrDf8pztQZLifdTImN2Ai/W0qwBNBTS73PQ0FT2?=
+ =?us-ascii?Q?sPoWL0ldZycOMq8oIvHkoJDk+qEVDqJNsufKZ7xr+DGv4Q8+ykdrSHwOZ4gA?=
+ =?us-ascii?Q?PkEU8EM6ASlPrSDatw6LvAMzoJe0ydTY+yws/v6PcrPzhbEot36M/GpjBPQr?=
+ =?us-ascii?Q?g57ulq+nBTWkXDzkb+UMkvxwJ620iHAjjY2euLn4tOeVarUbxxdbhQJ5uBQg?=
+ =?us-ascii?Q?RO6NLHYONoOfARncwNckyj1dvu8PaYWMgT+DrelPC0VpBUrKJbhlzCrAIQcU?=
+ =?us-ascii?Q?UTYoAK21nMjJylmZFtPPlRkUAsAGWch5w6QZjb/hm7vk3Tcs0fEi5LbrvRS7?=
+ =?us-ascii?Q?C9zffYv20+0O20XsGfBYSz4uYnqg4dIyortBtXKx3HYSj0c+kqvWTHfMRyCX?=
+ =?us-ascii?Q?A5DCnVfIe/3QtZuslMov+IyAVqFwMS4fV1M0I4QU/uqR9cLNdCz7rKGIkmxK?=
+ =?us-ascii?Q?WkAVxnKSaX19h4R4H8rhk83+nd66EGNcIuGFShC878lyNB+S6Ufl68G33x+Q?=
+ =?us-ascii?Q?o0ey4cUuza/qEA/TKaG+XrysH/OMm0wKPd5hhesfrPSrVlHZw+Hdkv4AXn/q?=
+ =?us-ascii?Q?TzkWaQKyzYwVsnYmD+KpWC/eq3tnczLJ2jqFEXChNhOu/7P3njItGKZmbkLE?=
+ =?us-ascii?Q?1iFJqx/OymRRRci9hSkUfAw0WBWePxrYwleglYlXLEO1kWi6TsgOQc4SlkgC?=
+ =?us-ascii?Q?Zfa+APxSaYPD0Wu/thglYvlhEb5KERdPhrXSGIOW4krqwr+vpPpTGPOW2ShP?=
+ =?us-ascii?Q?tSEKF2nCgWKq+sLCxDWZEXYwpt5RTr1FnqruGn34tf5VEL1QbQhDwzgh61L8?=
+ =?us-ascii?Q?5g98VycPGlP62PnzWRHXqglUC9zVlFHYYq9aDt1bXqeuQanSuQbWdTMXSOQJ?=
+ =?us-ascii?Q?PyoIoq+O7n9ENSFTAjOfGhq/Lko6qe5qfrPlmPv0VDXdz9njkGYKU9lPopba?=
+ =?us-ascii?Q?YtEjvwrndiyv2chBkik9trkCYdEnaN3iovce1zFrfeoWJbGefZoWU6FX7S9M?=
+ =?us-ascii?Q?utY3EqT7t2N8DQvLHPksHuDkAlNSAqkAZtwJLmbQSKuezwMHZavptH5ppDHZ?=
+ =?us-ascii?Q?6VwgAWGvyAOEuo513O+jF5lO6e8koXF8Wjt8jGJhh4OGX7SWTZy/cu2w4xsA?=
+ =?us-ascii?Q?HksSpYjl+8TO94uUHO8PZptNrTWvIglXtu/PhDrxFWaXlUYjtsjVWBl1D3RL?=
+ =?us-ascii?Q?gKMShcfw+pD9zzKjXW3+X7s4eCZFW1kAxIwjpQO7Ql2bjCIGC5eF5STnY9ss?=
+ =?us-ascii?Q?JUxnD8CT3inNdaMp09VOxrZ2BYmGksc0mPXcoVBWI7gOo5pk+4jDSQhdymW1?=
+ =?us-ascii?Q?xPGUc2wl3slJoj5JsKs0z9zQ0x+/dT8/2njgkVODJRMyZl0RGK5MJfYx3uoW?=
+ =?us-ascii?Q?wTmROAncSIBmGSxaUj6sEdpLjDhN1UZUJ+SYT7H9sqHISb86VjF64KYSbw1c?=
+ =?us-ascii?Q?DqUTx/d0o0pJElcj+GD0sYXXcVryfGYTf3EchwSWO5gJfGHLB1iLHTCSCO3A?=
+ =?us-ascii?Q?R4bZAoD9ehWFr0aeSbgFLiUOkEgNpbf6LdGdK3A9oPpjQqntw+rAgtRXr0Yb?=
+ =?us-ascii?Q?jDvaoPFNba+jTsWJencJPOxhaRMu427/hp9IMonIs++Zv8KI5Td5HZzT6E0r?=
+ =?us-ascii?Q?O8N9iFuz7G2Gfwr0XaiS09pmpPA35V3mIWTd2Teq46b3nvFx/0p9YdgLkjQM?=
+ =?us-ascii?Q?l8tJXqyuLbcxT3vHjWXHj6U=3D?=
+MIME-Version: 1.0
+
+------=_Part_68710_325875922.1770819322004
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Vodafone E2E Service Change Management
+Planned Maintenance Notice
+
+
+Dear ACME CORP,
+
+Please be advised that the Planned Works have been Completed: CRQ0000013129=
+27
+
+Detailed Description of Works:
+
+Please be informed, MW has been scheduled for cut over works on FOC 96C SW-=
+PR WESTERN BLOC at KM15.7 from TM Node SW on BBG001 Link 2 between Pantai R=
+emis - Lekir (PR-LKR) sector
+
+Scheduled Start/End Date & Outage Window:
+
+09/02/2026 16:01 to 09/02/2026 22:30 UTC
+
+Impact Assessment:
+
+Expect all traffic facing Singapore to experience switching hit, in the lea=
+st likely scenario, could last for any duration within the maintenance wind=
+ow.
+
+
+
+Services Impacted:
+
+Services Affected Customer Service Impact Address Service Typ=
+e Service Model Customer Reference Node
+X0013337A ACME CORP Loss of Service MUMBAI PLOT 37, CHANDIVALI =
+FAR,PLOT 3,CHANDIVALI FARM ROAD,MUMBAI,*IN >>> SINGAPORE AYER RAJAH CRESCEN=
+T,20,AYER RAJAH CRESCENT,'SINGAPORE,*SG 160510GLA / 10.31G N/A N=
+/A SNGS00B61 <> MUMS00031
+
+
+
+For any questions or concerns regarding this maintenance please contact Vod=
+afone E2E Service Change Management using the email address below. If your =
+service remains affected upon the conclusion of the planned maintenance win=
+dow provided, please contact the appropriate Vodafone Service Desk to repor=
+t a fault.
+
+Best regards
+Vodafone E2E Service Change Management
+Vodafone International Networks
+Email: TDOIntnlChangeManagement@vodafone.com
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limited a=
+nd Hutchison 3G UK Limited and this email is sent on behalf of Vodafone Lim=
+ited and/or Hutchison 3G UK Limited. The message and any attachment(s) are =
+confidential, may be legally privileged and are intended solely for the att=
+ention of the addressee(s). If you are not the intended recipient or you h=
+ave received this email in error, please notify the sender immediately, del=
+ete it and any attachments from your system and do not copy, disclose or us=
+e its contents for any purpose. This transmission cannot be guaranteed to b=
+e secure or error-free. Any views or opinions expressed in this message are=
+ those of the author only.
+
+Vodafone Limited. Registered in England & Wales | Company no 01471587. Voda=
+fone House, The Connection, Newbury, Berkshire, RG14 2FN. Authorised & Regu=
+lated by the Financial Conduct Authority for consumer credit lending and in=
+surance distribution activity (Financial Services Register No. 712210).
+
+Hutchison 3G UK Limited. Registered in England and Wales | Company number 3=
+885486. Registered Office: 450 Longwater Avenue, Green Park, Reading, Berks=
+hire, RG2 6GF. Authorised & Regulated by the Financial Conduct Authority fo=
+r consumer credit (Financial Services Register No. 738979).
+
+VodafoneThree is a holding company of Vodafone Limited and Hutchison 3G UK =
+Limited, see www.VodafoneThree.com to learn =
+more.
+
+------=_Part_68710_325875922.1770819322004
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+
+=
+head>
+
+Vodafone E2E Service Change Management
+Planned Maintenance Notice=
+
+
+Dear ACME CORP,
+
+Please be advised that the Planned Works have been Completed: CRQ0000013129=
+27
+
+Detailed Description of Works:
+
+Please be informed, MW has been scheduled for cut over works on FOC 96C SW-=
+PR WESTERN BLOC at KM15.7 from TM Node SW on BBG001 Link 2 between Pantai R=
+emis - Lekir (PR-LKR) sector
+
+
+Scheduled Start/End Date & Outage Window:
+
+09/02/2026 16:01 to 09/02/2026 22:30 UTC
+
+Impact Assessment:
+
+Expect all traffic facing Singapore to experience switching hit, in the lea=
+st likely scenario, could last for any duration within the maintenance wind=
+ow.
+
+
+
+
+Services Impacted:
+
+
+
+
+| Services Affected |
+Customer |
+Service Impact |
+Address |
+Service Type |
+Service Model |
+Customer Reference |
+Node |
+
+
+| X0013337A |
+ACME CORP |
+Loss of Service |
+MUMBAI PLOT 37, CHANDIVALI FAR,PLOT 3,CHA=
+NDIVALI FARM ROAD,MUMBAI,*IN >>> SINGAPORE AYER RAJAH CRESCENT,20,=
+AYER RAJAH CRESCENT,'SINGAPORE,*SG |
+160510GLA / 10.31G |
+N/A |
+N/A |
+SNGS00B61 <> MUMS00031 |
+
+
+
+
+
+
+For any questions or concerns regarding this maintenance please contact Vod=
+afone E2E Service Change Management using the email address below. If your =
+service remains affected upon the conclusion of the planned maintenance win=
+dow provided, please contact the
+ appropriate Vodafone Service Desk to report a fault.
+
+Best regards
+Vodafone E2E Service Change Management
+Vodafone International Networks
+Email: TDOIntnlChangeManagement@vodafone.com
+
+
+VodafoneThree Holdings Limited is the holding company of Vodafone Limite=
+d and Hutchison 3G UK Limited and this email is sent on behalf of Vodafone =
+Limited and/or Hutchison 3G UK Limited. The message and any attachment(s) a=
+re confidential, may be legally
+ privileged and are intended solely for the attention of the addressee(s).&=
+nbsp; If you are not the intended recipient or you have received this email=
+ in error, please notify the sender immediately, delete it and any attachme=
+nts from your system and do not copy,
+ disclose or use its contents for any purpose. This transmission cannot be =
+guaranteed to be secure or error-free. Any views or opinions expressed in t=
+his message are those of the author only.
+Vodafone Limited. Registered in England & Wales | C=
+ompany no 01471587. Vodafone House, The Connection, Newbury, Berkshire, RG1=
+4 2FN. Authorised & Regulated by the Financial Conduct Authority for co=
+nsumer credit lending and insurance distribution
+ activity (Financial Services Register No. 712210).
+Hutchison 3G UK Limited. Registered in England and Wale=
+s | Company number 3885486. Registered Office: 450 Longwater Avenue, Green =
+Park, Reading, Berkshire, RG2 6GF. Authorised & Regulated by the Financ=
+ial Conduct Authority for consumer credit
+ (Financial Services Register No. 738979).
+VodafoneThree is a holding company of Vodafone Limited =
+and Hutchison 3G UK Limited, see
+www.VodafoneThree.com<=
+/a> to learn more.
+
+
+
+------=_Part_68710_325875922.1770819322004--
diff --git a/tests/unit/data/vodafone/vodafone3_result.json b/tests/unit/data/vodafone/vodafone3_result.json
new file mode 100644
index 00000000..6a2a72d3
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone3_result.json
@@ -0,0 +1,16 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1770676200,
+ "maintenance_id": "CRQ000001312927",
+ "start": 1770652860,
+ "status": "COMPLETED",
+ "summary": "Please be informed, MW has been scheduled for cut over works on FOC 96C SW-PR WESTERN BLOC at KM15.7 from TM Node SW on BBG001 Link 2 between Pantai Remis - Lekir (PR-LKR) sector"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone3_result_combined.json b/tests/unit/data/vodafone/vodafone3_result_combined.json
new file mode 100644
index 00000000..8768bdb7
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone3_result_combined.json
@@ -0,0 +1,21 @@
+[
+ {
+ "account": "ACME CORP",
+ "circuits": [
+ {
+ "circuit_id": "X0013337A",
+ "impact": "OUTAGE"
+ }
+ ],
+ "end": 1770676200,
+ "maintenance_id": "CRQ000001312927",
+ "organizer": "networkchangemanagement@vodafone.com",
+ "provider": "vodafone",
+ "sequence": 1,
+ "stamp": 1770819321,
+ "start": 1770652860,
+ "status": "COMPLETED",
+ "summary": "Please be informed, MW has been scheduled for cut over works on FOC 96C SW-PR WESTERN BLOC at KM15.7 from TM Node SW on BBG001 Link 2 between Pantai Remis - Lekir (PR-LKR) sector",
+ "uid": "0"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/test_e2e.py b/tests/unit/test_e2e.py
index e8930493..35319eef 100644
--- a/tests/unit/test_e2e.py
+++ b/tests/unit/test_e2e.py
@@ -41,6 +41,7 @@
Telstra,
Turkcell,
Verizon,
+ Vodafone,
Windstream,
Zayo,
)
@@ -970,6 +971,22 @@
Path(dir_path, "data", "date", "email_date_1_result.json"),
],
),
+ # Vodafone
+ (
+ Vodafone,
+ [("email", Path(dir_path, "data", "vodafone", "vodafone1.eml"))],
+ [Path(dir_path, "data", "vodafone", "vodafone1_result_combined.json")],
+ ),
+ (
+ Vodafone,
+ [("email", Path(dir_path, "data", "vodafone", "vodafone2.eml"))],
+ [Path(dir_path, "data", "vodafone", "vodafone2_result_combined.json")],
+ ),
+ (
+ Vodafone,
+ [("email", Path(dir_path, "data", "vodafone", "vodafone3.eml"))],
+ [Path(dir_path, "data", "vodafone", "vodafone3_result_combined.json")],
+ ),
# Windstream
(
Windstream,
diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py
index fc7d839b..00b0e39c 100644
--- a/tests/unit/test_parsers.py
+++ b/tests/unit/test_parsers.py
@@ -37,6 +37,7 @@
from circuit_maintenance_parser.parsers.telstra import HtmlParserTelstra1, HtmlParserTelstra2
from circuit_maintenance_parser.parsers.turkcell import HtmlParserTurkcell1
from circuit_maintenance_parser.parsers.verizon import HtmlParserVerizon1
+from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1
from circuit_maintenance_parser.parsers.windstream import HtmlParserWindstream1
from circuit_maintenance_parser.parsers.zayo import HtmlParserZayo1, SubjectParserZayo1
@@ -751,6 +752,22 @@ def default(self, o):
Path(dir_path, "data", "verizon", "verizon5.html"),
Path(dir_path, "data", "verizon", "verizon5_result.json"),
),
+ # Vodafone
+ (
+ HtmlParserVodafone1,
+ Path(dir_path, "data", "vodafone", "vodafone1.eml"),
+ Path(dir_path, "data", "vodafone", "vodafone1_result.json"),
+ ),
+ (
+ HtmlParserVodafone1,
+ Path(dir_path, "data", "vodafone", "vodafone2.eml"),
+ Path(dir_path, "data", "vodafone", "vodafone2_result.json"),
+ ),
+ (
+ HtmlParserVodafone1,
+ Path(dir_path, "data", "vodafone", "vodafone3.eml"),
+ Path(dir_path, "data", "vodafone", "vodafone3_result.json"),
+ ),
# Windstream
(
HtmlParserWindstream1,
From 0583d6c745ce8358bfe9d7954465c4584a9cdeef Mon Sep 17 00:00:00 2001
From: Arjan Koopen
Date: Wed, 6 May 2026 23:53:57 +0200
Subject: [PATCH 2/3] Add changelog item
---
changes/416.added | 1 +
1 file changed, 1 insertion(+)
create mode 100644 changes/416.added
diff --git a/changes/416.added b/changes/416.added
new file mode 100644
index 00000000..f00369c2
--- /dev/null
+++ b/changes/416.added
@@ -0,0 +1 @@
+Added parser for Vodafone.
From a5c25d1e6a74dd84747658e7ca5c56d2ab19b26f Mon Sep 17 00:00:00 2001
From: Arjan Koopen
Date: Tue, 12 May 2026 12:09:20 +0200
Subject: [PATCH 3/3] Add email subject parser for status and maintenance_id,
plus small other fixes that came up during PR review.
---
.../parsers/vodafone.py | 67 ++++++++++++-------
circuit_maintenance_parser/provider.py | 4 +-
.../unit/data/vodafone/vodafone1_result.json | 1 -
tests/unit/data/vodafone/vodafone2.eml | 4 +-
.../unit/data/vodafone/vodafone2_result.json | 1 -
.../unit/data/vodafone/vodafone3_result.json | 1 -
.../unit/data/vodafone/vodafone4_subject.eml | 1 +
.../vodafone/vodafone4_subject_result.json | 6 ++
tests/unit/test_parsers.py | 7 +-
9 files changed, 59 insertions(+), 33 deletions(-)
create mode 100644 tests/unit/data/vodafone/vodafone4_subject.eml
create mode 100644 tests/unit/data/vodafone/vodafone4_subject_result.json
diff --git a/circuit_maintenance_parser/parsers/vodafone.py b/circuit_maintenance_parser/parsers/vodafone.py
index f3959f12..d0e71797 100644
--- a/circuit_maintenance_parser/parsers/vodafone.py
+++ b/circuit_maintenance_parser/parsers/vodafone.py
@@ -2,12 +2,13 @@
import logging
import re
-from typing import Dict, List
+from typing import Any, Dict, List
+from bs4 import BeautifulSoup
from bs4.element import ResultSet # type: ignore
from dateutil import parser
-from circuit_maintenance_parser.parser import Html, Impact, Status
+from circuit_maintenance_parser.parser import EmailSubjectParser, Html, Impact, Status
logger = logging.getLogger(__name__)
@@ -15,9 +16,9 @@
class HtmlParserVodafone1(Html):
"""Notifications Parser for Vodafone notifications."""
- def parse_html(self, soup: ResultSet) -> List[Dict]:
+ def parse_html(self, soup: BeautifulSoup) -> List[Dict]:
"""Execute parsing."""
- data: Dict[str] = {"circuits": []}
+ data: Dict[str, Any] = {"circuits": []}
self.parse_crq(soup, data)
self.parse_tables(soup.find_all("table"), data)
self.parse_bold(soup.find_all("b"), data)
@@ -46,11 +47,11 @@ def parse_tables(self, tables: ResultSet, data: Dict):
elif "Services Affected" in col_mapping and col == col_mapping["Services Affected"]:
cid = td_elem.text.strip()
elif "Service Impact" in col_mapping and col == col_mapping["Service Impact"]:
- # not sure if other impact types exist, can be expanded of need-be
+ # not sure if other impact types exist, can be expanded of need-be. Default to DEGRADED.
if "loss of service" in td_elem.text.lower():
impact = Impact("OUTAGE")
else:
- impact = Impact("OUTAGE")
+ impact = Impact("DEGRADED")
col += 1
# at the end of the table row, add circuits to list, if defined
@@ -66,10 +67,14 @@ def parse_bold(self, bolds: ResultSet, data: Dict):
"""
window = 0
for bold in bolds:
+ text_lower = bold.text.lower()
+
# find start/end date/time
- if (
- data["status"] == Status("RE-SCHEDULED") and "new scheduled start" in bold.text.lower()
- ) or "scheduled start" in bold.text.lower():
+ # in case the window is re-schedulded, the original and new window are listed; ignore original window
+ if "original scheduled start" in text_lower:
+ continue
+
+ if "scheduled start" in text_lower:
window_next = bold.next_sibling
while window_next:
text = window_next.text.strip()
@@ -77,8 +82,9 @@ def parse_bold(self, bolds: ResultSet, data: Dict):
window = text
break
window_next = window_next.next_sibling
+
# find summary
- elif "description" in bold.text.lower():
+ if "description" in text_lower:
description_next = bold.next_sibling
while description_next:
text = description_next.text.strip()
@@ -95,22 +101,33 @@ def parse_bold(self, bolds: ResultSet, data: Dict):
def parse_crq(self, soup: ResultSet, data: Dict):
"""Vodafone maintenance_id's are in the format of CRQ[0-9] with 12 digits.
- Before mentioning the CRQ, the status of the maintenance can be derived, for example:
-
Please be advised that the Planned Works have been Completed: CRQ000001312927
"""
text = soup.get_text(separator=" ")
- match = re.search(r"\b(.*)[\s:]+(CRQ\d{12})\b", text)
+ match = re.search(r"\bCRQ\d{12}\b", text)
if match:
- data["maintenance_id"] = match.group(2)
-
- # derive status
- if "postponed" in match.group(1).lower():
- data["status"] = Status("CANCELLED")
- elif "completed" in match.group(1).lower():
- data["status"] = Status("COMPLETED")
- elif "rescheduled" in match.group(1).lower():
- data["status"] = Status("RE-SCHEDULED")
- # default status
- else:
- data["status"] = Status("CONFIRMED")
+ data.setdefault("maintenance_id", match.group(0))
+
+
+class SubjectParserVodafone1(EmailSubjectParser):
+ """Parse status and (when present) the CRQ from the subject line."""
+
+ def parse_subject(self, subject: str) -> List[Dict]:
+ """Parse the email subject."""
+ data: Dict = {}
+ subject_lower = subject.lower()
+
+ if "completed" in subject_lower:
+ data["status"] = Status("COMPLETED")
+ elif "rescheduled" in subject_lower:
+ data["status"] = Status("RE-SCHEDULED")
+ elif "postponed" in subject_lower or "cancelled" in subject_lower:
+ data["status"] = Status("CANCELLED")
+ else:
+ data["status"] = Status("CONFIRMED")
+
+ crq_match = re.search(r"\bCRQ\d{12}\b", subject)
+ if crq_match:
+ data["maintenance_id"] = crq_match.group(0)
+
+ return [data]
diff --git a/circuit_maintenance_parser/provider.py b/circuit_maintenance_parser/provider.py
index 3975571c..40d70ccc 100644
--- a/circuit_maintenance_parser/provider.py
+++ b/circuit_maintenance_parser/provider.py
@@ -44,7 +44,7 @@
from circuit_maintenance_parser.parsers.telstra import HtmlParserTelstra1, HtmlParserTelstra2
from circuit_maintenance_parser.parsers.turkcell import HtmlParserTurkcell1
from circuit_maintenance_parser.parsers.verizon import HtmlParserVerizon1
-from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1
+from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1, SubjectParserVodafone1
from circuit_maintenance_parser.parsers.windstream import HtmlParserWindstream1
from circuit_maintenance_parser.parsers.zayo import HtmlParserZayo1, SubjectParserZayo1
from circuit_maintenance_parser.processor import CombinedProcessor, GenericProcessor, SimpleProcessor
@@ -571,7 +571,7 @@ class Vodafone(GenericProvider):
_processors: List[GenericProcessor] = PrivateAttr(
[
- CombinedProcessor(data_parsers=[EmailDateParser, HtmlParserVodafone1]),
+ CombinedProcessor(data_parsers=[EmailDateParser, SubjectParserVodafone1, HtmlParserVodafone1]),
]
)
_default_organizer = PrivateAttr("networkchangemanagement@vodafone.com")
diff --git a/tests/unit/data/vodafone/vodafone1_result.json b/tests/unit/data/vodafone/vodafone1_result.json
index f8aef000..e1596cbb 100644
--- a/tests/unit/data/vodafone/vodafone1_result.json
+++ b/tests/unit/data/vodafone/vodafone1_result.json
@@ -10,7 +10,6 @@
"end": 1778040000,
"maintenance_id": "CRQ000001325565",
"start": 1778011200,
- "status": "CONFIRMED",
"summary": "3rd Party Essential Works to carry out maintenance to move their cable to new reroute Due to road construction works"
}
]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone2.eml b/tests/unit/data/vodafone/vodafone2.eml
index 0ba320a4..2a649a24 100644
--- a/tests/unit/data/vodafone/vodafone2.eml
+++ b/tests/unit/data/vodafone/vodafone2.eml
@@ -83,8 +83,8 @@ From: Network Change
Reply-To: Network Change
To:
Message-ID: <20012384.98430.1774448475992@GBVLS-AS360>
-Subject: Rescheduled 3rd Party Planned Works CRQ000001319054 Affecting I3
- NET BV Services
+Subject: Rescheduled 3rd Party Planned Works CRQ000001319054 Affecting ACME
+ CORP Services
Content-Type: multipart/alternative;
boundary="----=_Part_98429_663222437.1774448475992"
Return-Path: networkchangemanagement@vodafone.com
diff --git a/tests/unit/data/vodafone/vodafone2_result.json b/tests/unit/data/vodafone/vodafone2_result.json
index b155076d..accac6ab 100644
--- a/tests/unit/data/vodafone/vodafone2_result.json
+++ b/tests/unit/data/vodafone/vodafone2_result.json
@@ -10,7 +10,6 @@
"end": 1776038400,
"maintenance_id": "CRQ000001319054",
"start": 1775433600,
- "status": "RE-SCHEDULED",
"summary": "Rescheduled 3rd Party Planned Works to perform cable repair work in their partner's network"
}
]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone3_result.json b/tests/unit/data/vodafone/vodafone3_result.json
index 6a2a72d3..3eaeff76 100644
--- a/tests/unit/data/vodafone/vodafone3_result.json
+++ b/tests/unit/data/vodafone/vodafone3_result.json
@@ -10,7 +10,6 @@
"end": 1770676200,
"maintenance_id": "CRQ000001312927",
"start": 1770652860,
- "status": "COMPLETED",
"summary": "Please be informed, MW has been scheduled for cut over works on FOC 96C SW-PR WESTERN BLOC at KM15.7 from TM Node SW on BBG001 Link 2 between Pantai Remis - Lekir (PR-LKR) sector"
}
]
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone4_subject.eml b/tests/unit/data/vodafone/vodafone4_subject.eml
new file mode 100644
index 00000000..3d6ee443
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone4_subject.eml
@@ -0,0 +1 @@
+Completed Vodafone E2E Service Change Management Planned Works CRQ000001312927 Affecting ACME CORP Services
\ No newline at end of file
diff --git a/tests/unit/data/vodafone/vodafone4_subject_result.json b/tests/unit/data/vodafone/vodafone4_subject_result.json
new file mode 100644
index 00000000..e19cfde0
--- /dev/null
+++ b/tests/unit/data/vodafone/vodafone4_subject_result.json
@@ -0,0 +1,6 @@
+[
+ {
+ "maintenance_id": "CRQ000001312927",
+ "status": "COMPLETED"
+ }
+]
\ No newline at end of file
diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py
index 00b0e39c..d51824bf 100644
--- a/tests/unit/test_parsers.py
+++ b/tests/unit/test_parsers.py
@@ -37,7 +37,7 @@
from circuit_maintenance_parser.parsers.telstra import HtmlParserTelstra1, HtmlParserTelstra2
from circuit_maintenance_parser.parsers.turkcell import HtmlParserTurkcell1
from circuit_maintenance_parser.parsers.verizon import HtmlParserVerizon1
-from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1
+from circuit_maintenance_parser.parsers.vodafone import HtmlParserVodafone1, SubjectParserVodafone1
from circuit_maintenance_parser.parsers.windstream import HtmlParserWindstream1
from circuit_maintenance_parser.parsers.zayo import HtmlParserZayo1, SubjectParserZayo1
@@ -768,6 +768,11 @@ def default(self, o):
Path(dir_path, "data", "vodafone", "vodafone3.eml"),
Path(dir_path, "data", "vodafone", "vodafone3_result.json"),
),
+ (
+ SubjectParserVodafone1,
+ Path(dir_path, "data", "vodafone", "vodafone4_subject.eml"),
+ Path(dir_path, "data", "vodafone", "vodafone4_subject_result.json"),
+ ),
# Windstream
(
HtmlParserWindstream1,