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.
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..d0e71797
--- /dev/null
+++ b/circuit_maintenance_parser/parsers/vodafone.py
@@ -0,0 +1,133 @@
+"""Vodafone parser."""
+
+import logging
+import re
+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 EmailSubjectParser, Html, Impact, Status
+
+logger = logging.getLogger(__name__)
+
+
+class HtmlParserVodafone1(Html):
+ """Notifications Parser for Vodafone notifications."""
+
+ def parse_html(self, soup: BeautifulSoup) -> List[Dict]:
+ """Execute parsing."""
+ 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)
+
+ 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. Default to DEGRADED.
+ if "loss of service" in td_elem.text.lower():
+ impact = Impact("OUTAGE")
+ else:
+ impact = Impact("DEGRADED")
+ 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: Vodafone UK - Technology Operations=
+span> Essential Maintenance Notice Dear ACME CORP,
+ 06/04/2026 00:00 to 13/04/2026 00:00 UTC
+ """
+ window = 0
+ for bold in bolds:
+ text_lower = bold.text.lower()
+
+ # find start/end date/time
+ # 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()
+ if text != "":
+ window = text
+ break
+ window_next = window_next.next_sibling
+
+ # find summary
+ if "description" in 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.
+
+ Please be advised that the Planned Works have been Completed: CRQ000001312927
+ """
+ text = soup.get_text(separator=" ")
+ match = re.search(r"\bCRQ\d{12}\b", text)
+ if match:
+ 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 5b02c2b0..40d70ccc 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, 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
@@ -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, SubjectParserVodafone1, 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
+
+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 AnalystVodafoneThree 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..e1596cbb --- /dev/null +++ b/tests/unit/data/vodafone/vodafone1_result.json @@ -0,0 +1,15 @@ +[ + { + "account": "ACME CORP", + "circuits": [ + { + "circuit_id": "X0013337A", + "impact": "OUTAGE" + } + ], + "end": 1778040000, + "maintenance_id": "CRQ000001325565", + "start": 1778011200, + "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..2a649a24 --- /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 ChangeVodafone 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 | +
Vodafone UK Fixed
+Change Management AnalystVodafoneThree 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..accac6ab --- /dev/null +++ b/tests/unit/data/vodafone/vodafone2_result.json @@ -0,0 +1,15 @@ +[ + { + "account": "ACME CORP", + "circuits": [ + { + "circuit_id": "X0013337A", + "impact": "OUTAGE" + } + ], + "end": 1776038400, + "maintenance_id": "CRQ000001319054", + "start": 1775433600, + "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 ChangeVodafone 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 | +
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..3eaeff76 --- /dev/null +++ b/tests/unit/data/vodafone/vodafone3_result.json @@ -0,0 +1,15 @@ +[ + { + "account": "ACME CORP", + "circuits": [ + { + "circuit_id": "X0013337A", + "impact": "OUTAGE" + } + ], + "end": 1770676200, + "maintenance_id": "CRQ000001312927", + "start": 1770652860, + "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/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_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..d51824bf 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, SubjectParserVodafone1 from circuit_maintenance_parser.parsers.windstream import HtmlParserWindstream1 from circuit_maintenance_parser.parsers.zayo import HtmlParserZayo1, SubjectParserZayo1 @@ -751,6 +752,27 @@ 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"), + ), + ( + SubjectParserVodafone1, + Path(dir_path, "data", "vodafone", "vodafone4_subject.eml"), + Path(dir_path, "data", "vodafone", "vodafone4_subject_result.json"), + ), # Windstream ( HtmlParserWindstream1,