def test_send(self): with patch("smtplib.SMTP") as smtp: notify.send(self.config) instance = smtp.return_value # verify that sendmail() was called self.assertTrue(instance.sendmail.called) self.assertEqual(instance.sendmail.call_count, 1) # verify that the correct email is being sent to sendmail() self.assertEqual( config_parser.get_smtp_email(config=self.config), instance.sendmail.mock_calls[0][2]["from_addr"], ) self.assertEqual( config_parser.get_smtp_to_email(config=self.config), instance.sendmail.mock_calls[0][2]["to_addrs"], ) # verify that the message was passed to sendmail() self.assertIn( "Subject: icloud-docker: Two step authentication required", instance.sendmail.mock_calls[0][2]["msg"], )
def test_send_fail(self): with patch("smtplib.SMTP") as smtp: smtp.side_effect = Exception # Verify that a failure doesn't return a send_on timestamp sent_on = notify.send(self.config) self.assertEqual(None, sent_on)
def sync_drive(): last_send = None while True: config = config_parser.read_config() verbose = config_parser.get_verbose(config=config) username = config_parser.get_username(config=config) destination_path = config_parser.prepare_destination(config=config) if username and destination_path: try: api = PyiCloudService(apple_id=username, password=utils.get_password_from_keyring(username=username)) if not api.requires_2sa: sync_directory(drive=api.drive, destination_path=destination_path, root=destination_path, items=api.drive.dir(), top=True, filters=config['filters'], remove=config_parser.get_remove_obsolete(config=config), verbose=verbose) else: print('Error: 2FA is required. Please log in.') last_send = notify.send(config, last_send) except exceptions.PyiCloudNoStoredPasswordAvailableException: print('password is not stored in keyring. Please save the password in keyring.') sleep_for = config_parser.get_sync_interval(config=config) next_sync = (datetime.datetime.now() + datetime.timedelta(minutes=sleep_for)).strftime('%l:%M%p %Z on %b %d, %Y') print(f'Resyncing at {next_sync} ...') if sleep_for < 0: break time.sleep(sleep_for)
def test_dry_run_send(self): # send returns the datetime of the request self.assertIsInstance(notify.send(self.config, None, dry_run=True), datetime.datetime)
def test_no_smtp_config(self): # None is returned if email didn't send because of missing config self.assertIsNone(notify.send({}, None, dry_run=True))
def test_throttling(self): not_24_hours = datetime.datetime.now() # if less than 24 hours has passed since last send, then the same # datetime object is returned self.assertEqual(not_24_hours, notify.send(self.config, not_24_hours, dry_run=True))
def sync(): last_send = None enable_sync_drive = True enable_sync_photos = True drive_sync_interval = 0 photos_sync_interval = 0 sleep_for = 10 while True: config = read_config() username = config_parser.get_username(config=config) if username: try: if ENV_ICLOUD_PASSWORD_KEY in os.environ: password = os.environ.get(ENV_ICLOUD_PASSWORD_KEY) utils.store_password_in_keyring(username=username, password=password) else: password = utils.get_password_from_keyring( username=username) api = ICloudPyService( apple_id=username, password=password, cookie_directory=DEFAULT_COOKIE_DIRECTORY, ) if not api.requires_2sa: if "drive" in config and enable_sync_drive: sync_drive.sync_drive(config=config, drive=api.drive) drive_sync_interval = config_parser.get_drive_sync_interval( config=config) if "photos" in config and enable_sync_photos: sync_photos.sync_photos(config=config, photos=api.photos) photos_sync_interval = config_parser.get_photos_sync_interval( config=config) if "drive" not in config and "photos" not in config: LOGGER.warning( "Nothing to sync. Please add drive: and/or photos: section in config.yaml file." ) else: LOGGER.error("Error: 2FA is required. Please log in.") # Retry again sleep_for = config_parser.get_retry_login_interval( config=config) next_sync = ( datetime.datetime.now() + datetime.timedelta(seconds=sleep_for)).strftime("%c") LOGGER.info(f"Retrying login at {next_sync} ...") last_send = notify.send(config, last_send) sleep(sleep_for) continue except exceptions.ICloudPyNoStoredPasswordAvailableException: LOGGER.error( "Password is not stored in keyring. Please save the password in keyring." ) sleep_for = config_parser.get_retry_login_interval( config=config) next_sync = ( datetime.datetime.now() + datetime.timedelta(seconds=sleep_for)).strftime("%c") LOGGER.info(f"Retrying login at {next_sync} ...") last_send = notify.send(config, last_send) sleep(sleep_for) continue if "drive" not in config and "photos" in config: sleep_for = photos_sync_interval enable_sync_drive = False enable_sync_photos = True elif "drive" in config and "photos" not in config: sleep_for = drive_sync_interval enable_sync_drive = True enable_sync_photos = False elif ("drive" in config and "photos" in config and drive_sync_interval <= photos_sync_interval): sleep_for = photos_sync_interval - drive_sync_interval photos_sync_interval -= drive_sync_interval enable_sync_drive = True enable_sync_photos = False else: sleep_for = drive_sync_interval - photos_sync_interval drive_sync_interval -= photos_sync_interval enable_sync_drive = False enable_sync_photos = True next_sync = (datetime.datetime.now() + datetime.timedelta(seconds=sleep_for)).strftime("%c") LOGGER.info(f"Resyncing at {next_sync} ...") if (config_parser.get_drive_sync_interval(config=config) < 0 if "drive" in config else True and config_parser.get_photos_sync_interval( config=config) < 0 if "photos" in config else True): break sleep(sleep_for)