Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- feature: the icloud email username is now included in the email about 2sa authentication failing, for when an installation is configured for multiple icloud accounts.

## 1.27.2 (2025-03-29)

- fix: dates prior 1970 do not work on non linux [#1045](https://github.com/icloud-photos-downloader/icloud_photos_downloader/issues/1045)
Expand Down
1 change: 1 addition & 0 deletions src/icloudpd/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,7 @@ def core(
if smtp_username is not None or notification_email is not None:
send_2sa_notification(
logger,
username,
smtp_username,
smtp_password,
smtp_host,
Expand Down
10 changes: 7 additions & 3 deletions src/icloudpd/email_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

def send_2sa_notification(
logger: logging.Logger,
username: str,
smtp_email: Optional[str],
smtp_password: Optional[str],
smtp_host: str,
Expand Down Expand Up @@ -38,12 +39,15 @@ def send_2sa_notification(
subj = "icloud_photos_downloader: Two step authentication has expired"
date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M")

message_text = """Hello,
message_text = f"""Hello,

Two-step authentication has expired for the icloud_photos_downloader script.
{username}'s two-step authentication has expired for the icloud_photos_downloader script.
Please log in to your server and run the script manually to update two-step authentication."""

msg = f"From: {from_addr}\n" + f"To: {to_addr}\nSubject: {subj}\nDate: {date}\n\n{message_text}"
msg = (
f"From: {from_addr}\n"
+ f"To: {to_addr}\nSubject: {subj}\nDate: {date}\n\n{message_text}"
)

smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()
30 changes: 21 additions & 9 deletions tests/test_email_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def test_2sa_required_email_notification(self) -> None:
with vcr.use_cassette(os.path.join(self.vcr_path, "auth_requires_2fa.yml")):
with patch("smtplib.SMTP") as smtp:
# Pass fixed client ID via environment variable
runner = CliRunner(env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"})
runner = CliRunner(
env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"}
)
result = runner.invoke(
main,
[
Expand All @@ -59,15 +61,17 @@ def test_2sa_required_email_notification(self) -> None:
smtp_instance = smtp()
smtp_instance.connect.assert_called_once()
smtp_instance.starttls.assert_called_once()
smtp_instance.login.assert_called_once_with("jdoe+smtp@gmail.com", "password1")
smtp_instance.login.assert_called_once_with(
"jdoe+smtp@gmail.com", "password1"
)
smtp_instance.sendmail.assert_called_once_with(
"iCloud Photos Downloader <jdoe+smtp@gmail.com>",
"jdoe+notifications@gmail.com",
"From: iCloud Photos Downloader <jdoe+smtp@gmail.com>\n"
"To: jdoe+notifications@gmail.com\n"
"Subject: icloud_photos_downloader: Two step authentication has expired\n"
"Date: 01/01/2018 00:00\n\nHello,\n\n"
"Two-step authentication has expired for the icloud_photos_downloader script.\n"
"jdoe@gmail.com's two-step authentication has expired for the icloud_photos_downloader script.\n"
"Please log in to your server and run the script manually to update two-step "
"authentication.",
)
Expand All @@ -84,7 +88,9 @@ def test_2sa_notification_without_smtp_login_and_tls(self) -> None:
with vcr.use_cassette(os.path.join(self.vcr_path, "auth_requires_2fa.yml")):
with patch("smtplib.SMTP") as smtp:
# Pass fixed client ID via environment variable
runner = CliRunner(env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"})
runner = CliRunner(
env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"}
)
result = runner.invoke(
main,
[
Expand Down Expand Up @@ -114,7 +120,7 @@ def test_2sa_notification_without_smtp_login_and_tls(self) -> None:
"To: jdoe+notifications@gmail.com\n"
"Subject: icloud_photos_downloader: Two step authentication has expired\n"
"Date: 01/01/2018 00:00\n\nHello,\n\n"
"Two-step authentication has expired for the icloud_photos_downloader script.\n"
"jdoe@gmail.com's two-step authentication has expired for the icloud_photos_downloader script.\n"
"Please log in to your server and run the script manually to update two-step "
"authentication.",
)
Expand All @@ -131,7 +137,9 @@ def test_2sa_required_notification_script(self) -> None:
with vcr.use_cassette(os.path.join(self.vcr_path, "auth_requires_2fa.yml")):
with patch("subprocess.call") as subprocess_patched:
# Pass fixed client ID via environment variable
runner = CliRunner(env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"})
runner = CliRunner(
env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"}
)
result = runner.invoke(
main,
[
Expand Down Expand Up @@ -163,7 +171,9 @@ def test_2sa_required_email_notification_from(self) -> None:
with vcr.use_cassette(os.path.join(self.vcr_path, "auth_requires_2fa.yml")):
with patch("smtplib.SMTP") as smtp:
# Pass fixed client ID via environment variable
runner = CliRunner(env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"})
runner = CliRunner(
env={"CLIENT_ID": "EC5646DE-9423-11E8-BF21-14109FE0B321"}
)
result = runner.invoke(
main,
[
Expand All @@ -190,15 +200,17 @@ def test_2sa_required_email_notification_from(self) -> None:
smtp_instance = smtp()
smtp_instance.connect.assert_called_once()
smtp_instance.starttls.assert_called_once()
smtp_instance.login.assert_called_once_with("jdoe+smtp@gmail.com", "password1")
smtp_instance.login.assert_called_once_with(
"jdoe+smtp@gmail.com", "password1"
)
smtp_instance.sendmail.assert_called_once_with(
"JD <jdoe+notifications+from@gmail.com>",
"JD <jdoe+notifications@gmail.com>",
"From: JD <jdoe+notifications+from@gmail.com>\n"
"To: JD <jdoe+notifications@gmail.com>\n"
"Subject: icloud_photos_downloader: Two step authentication has expired\n"
"Date: 01/01/2018 00:00\n\nHello,\n\n"
"Two-step authentication has expired for the icloud_photos_downloader script.\n"
"jdoe@gmail.com's two-step authentication has expired for the icloud_photos_downloader script.\n"
"Please log in to your server and run the script manually to update two-step "
"authentication.",
)
Loading