Skip to content

feat: add automatic IMAP email bounce parser#299

Open
Shiva210Jyoti wants to merge 5 commits into
Kuldeeep18:mainfrom
Shiva210Jyoti:feat/imap-bounce-parser
Open

feat: add automatic IMAP email bounce parser#299
Shiva210Jyoti wants to merge 5 commits into
Kuldeeep18:mainfrom
Shiva210Jyoti:feat/imap-bounce-parser

Conversation

@Shiva210Jyoti

@Shiva210Jyoti Shiva210Jyoti commented Jun 16, 2026

Copy link
Copy Markdown

Description
Implements a periodic Celery task that connects to IMAP mailboxes and automatically detects/processes bounce notifications for accounts without webhook delivery.

Type of Change
✅ New feature

Related Issue
Closes #123

What's Changed

  • Added IMAP credential fields to ConnectedEmailAccount: imap_host, imap_port, imap_username, imap_password
  • Added check_imap_bounces periodic Celery task in campaigns/tasks.py
  • Connects via imaplib, searches INBOX for unread bounce subjects (Undelivered Mail Returned to Sender, Delivery Status Notification (Failure), Mail delivery failed)
  • Parses failed recipient from DSN headers (Final-Recipient, X-Failed-Recipients) with regex body fallback
  • Updates matching CampaignLead status to BOUNCED, scoped by organization following existing tenant-isolation pattern
  • Marks processed messages as \Seen to avoid reprocessing
  • Registered in CELERY_BEAT_SCHEDULE to run every 15 minutes
  • Per-account try/except with logger.error() so one account failure doesn't abort the task

No new dependencies — uses Python's built-in imaplib and email stdlib only

Verification
✅ Migration applies cleanly (python manage.py migrate campaigns)
✅ python manage.py check passes with no issues
✅ Follows existing @shared_task, logger, and tenant-scoping patterns
✅ Existing tasks.py functionality untouched

Closes #123

Summary by CodeRabbit

  • New Features
    • Added IMAP connection settings for connected email accounts (host, port, username, and encrypted password).
    • Introduced automated IMAP bounce detection that runs every 15 minutes and updates matching campaign leads.
  • Security
    • Added configurable field-level encryption driven by an environment-based encryption key.
    • Backfilled encryption for existing stored IMAP passwords.
  • Tests
    • Added automated test coverage for bounce parsing, lead status updates, multi-account resilience, and IMAP “seen” handling.

- Add IMAP credential fields to ConnectedEmailAccount (host, port, username, password)
- Add check_imap_bounces periodic Celery task
- Connects via imaplib, searches INBOX for bounce notification subjects
- Parses failed recipient from DSN headers with body fallback
- Updates matching CampaignLead status to BOUNCED, scoped by organization
- Marks processed messages as Seen to avoid reprocessing
- Registered in CELERY_BEAT_SCHEDULE, runs every 15 minutes
- Per-account error isolation so one failure doesn't abort the task

Closes Kuldeeep18#123
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 352df908-5aab-41d6-a524-f2877c09b2a4

📥 Commits

Reviewing files that changed from the base of the PR and between c6996f3 and cef6892.

📒 Files selected for processing (1)
  • backend/campaigns/fields.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/campaigns/fields.py

📝 Walkthrough

Walkthrough

Adds symmetric field encryption infrastructure, extends ConnectedEmailAccount with IMAP configuration fields (using encrypted password storage), implements a new Celery task check_imap_bounces that connects to each configured IMAP account, parses unseen bounce notification emails, marks matched CampaignLead records as BOUNCED, schedules the task to run every 900 seconds, and provides comprehensive test coverage.

Changes

IMAP Bounce Detection Feature with Encryption

Layer / File(s) Summary
Encryption infrastructure and configuration
backend/backend/settings.py, backend/campaigns/encryption.py, requirements.txt
Implements Fernet-based symmetric encryption/decryption with environment-variable key derivation (FIELD_ENCRYPTION_KEY), DEBUG-mode deterministic fallback, and production validation; provides encrypt_value, decrypt_value, and is_encrypted helpers; adds cryptography dependency.
EncryptedTextField Django field
backend/campaigns/fields.py
Defines a model field that transparently encrypts values on write and decrypts on read, with migration-safe deconstruction.
ConnectedEmailAccount IMAP schema
backend/campaigns/models.py, backend/campaigns/migrations/0009_connectedemailaccount_imap_fields.py
Adds imap_host, imap_port (default 993), imap_username, and imap_password (encrypted) fields to ConnectedEmailAccount model with a new migration depending on 0008_merge_20260610_2213.
Data encryption migration
backend/campaigns/migrations/0010_encrypt_imap_password.py
Iterates existing ConnectedEmailAccount records, encrypts plaintext imap_password values (skipping already-encrypted), alters field to EncryptedTextField, and persists updates via RunPython.
IMAP bounce detection task
backend/campaigns/tasks.py
Expands imports with imaplib, email parsing, and re; adds ConnectedEmailAccount to model imports; implements bounce subject pattern matching, recipient extraction from headers/body, CampaignLead BOUNCED marking with completion checks, IMAP4/SSL connection/message processing, and the check_imap_bounces Celery task.
Celery Beat scheduling
backend/backend/settings.py
Registers check-imap-bounces-every-15-minutes in CELERY_BEAT_SCHEDULE targeting campaigns.tasks.check_imap_bounces at 900-second interval.
Bounce detection test suite
backend/campaigns/tests.py
Adds EmailMessage and MagicMock imports; extends task imports with check_imap_bounces; introduces CheckImapBouncesTests class with helpers for bounce email construction, IMAP account/lead setup, IMAP mocking, and tests covering bounce parsing/status updates, account skipping, per-account resilience, message seen-flagging, and non-bounce filtering.

Sequence Diagram

sequenceDiagram
  participant CeleryBeat
  participant check_imap_bounces
  participant IMAP4_SSL as IMAP4_SSL Server
  participant CampaignLead as CampaignLead DB

  CeleryBeat->>check_imap_bounces: trigger (every 900s)
  check_imap_bounces->>check_imap_bounces: query ConnectedEmailAccount with imap_host
  loop For each IMAP account
    check_imap_bounces->>check_imap_bounces: decrypt imap_password using EncryptedTextField
    check_imap_bounces->>IMAP4_SSL: login(imap_host, imap_port, imap_username, password)
    check_imap_bounces->>IMAP4_SSL: SEARCH UNSEEN messages in INBOX
    IMAP4_SSL-->>check_imap_bounces: message IDs
    check_imap_bounces->>IMAP4_SSL: FETCH RFC822 for each message
    IMAP4_SSL-->>check_imap_bounces: raw email bytes
    check_imap_bounces->>check_imap_bounces: parse subject, extract bounced recipient email
    check_imap_bounces->>CampaignLead: find by recipient email+connected_account (case-insensitive)
    check_imap_bounces->>CampaignLead: update status=BOUNCED, trigger completion check
    check_imap_bounces->>IMAP4_SSL: STORE message +FLAGS \Seen
  end
  check_imap_bounces-->>CeleryBeat: return "Processed N IMAP bounces."
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • #123 (LO-032: Automatic IMAP Email Bounce Parser) — This PR directly implements the complete feature: adds IMAP configuration fields to ConnectedEmailAccount, creates the check_imap_bounces Celery task with bounce recognition logic, parses failed recipient addresses from headers/body, updates CampaignLead status to BOUNCED, marks IMAP emails as read, and schedules periodic execution via Celery Beat.

Poem

🐇 Hop hop, through the inbox I go,
Sniffing out bounces, high and low,
Encrypted secrets, locked up tight,
"Undelivered Mail" — marked in sight,
The lead gets BOUNCED, the list stays clean,
Every fifteen minutes, I run the scene! 📬

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add automatic IMAP email bounce parser' accurately and concisely describes the main feature introduced: automated IMAP bounce detection and processing.
Linked Issues check ✅ Passed The PR fully implements all core requirements from issue #123: periodic Celery task, IMAP mailbox connection, bounce subject matching, email parsing, CampaignLead status updates, and message flagging as read.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to the bounce parser feature: IMAP credentials, encryption infrastructure, periodic task, migrations, and tests. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Shiva210Jyoti

Copy link
Copy Markdown
Author

@Kuldeeep18 ready for your review!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/campaigns/models.py`:
- Line 28: The imap_password field in the Campaign model is storing credentials
as plaintext, which is a critical security vulnerability. Replace the plain
CharField definition for imap_password with an encrypted field type from
django-encrypted-model-fields library or similar encryption solution. First
install the library, then change the imap_password field type from
models.CharField to the appropriate encrypted field type provided by the library
(typically EncryptedCharField), which will transparently encrypt the password
when storing it and decrypt it when retrieving it from the database.

In `@backend/campaigns/tasks.py`:
- Line 742: The imaplib.IMAP4_SSL connection in the account processing logic is
created without a timeout parameter, which can cause indefinite hangs if the
remote server is unresponsive or network issues occur. Add a timeout parameter
to the IMAP4_SSL constructor call to ensure that connection attempts fail
gracefully after a reasonable time period rather than blocking the Celery worker
indefinitely and preventing other accounts from being processed.
- Around line 796-804: The try-except blocks in the IMAP cleanup section (where
imap_conn.close() and imap_conn.logout() are called) silently suppress
exceptions with pass statements, making it impossible to debug connection or
resource issues. Replace each pass statement with a logging call that captures
the exception details at debug or warning level. For both the close() and
logout() calls, add a logger.debug or logger.warning statement (with the
exception included) so that cleanup failures are visible in logs while still
allowing the task to complete without failing on cleanup errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e1f538d9-b04b-4e07-bb53-f20a68b6f598

📥 Commits

Reviewing files that changed from the base of the PR and between 90052f9 and fbf56d0.

📒 Files selected for processing (5)
  • backend/backend/settings.py
  • backend/campaigns/migrations/0009_connectedemailaccount_imap_fields.py
  • backend/campaigns/models.py
  • backend/campaigns/tasks.py
  • backend/db.sqlite3

Comment thread backend/campaigns/models.py Outdated
Comment thread backend/campaigns/tasks.py Outdated
Comment thread backend/campaigns/tasks.py Outdated
@Kuldeeep18

Copy link
Copy Markdown
Owner

🚀 PR Guidelines — Read Before Raising a PR

Hey contributors 👋

I’m LeadOrbit's Bot, and I’ll review every PR before it gets merged.

✅ Your PR will only be merged if:

  • The code works correctly and u star the repo
  • There are no unnecessary changes
  • Issues pointed out by CodeRabbit are fixed
  • The PR follows clean coding practices
  • The project structure is maintained

❌ PRs that may be rejected:

  • Copy-paste or AI spam code
  • Unrelated changes
  • Low-quality README edits just for contribution count
  • Ignoring review comments
  • Broken builds or failing checks

Before submitting:

  1. Run and test your code properly
  2. Resolve all CodeRabbit suggestions
  3. Keep your PR focused and clean

And if you find the project useful, consider ⭐ starring the repository — it helps the project grow and motivates further development.

Quality contributions > PR count.

- Encrypt imap_password using project's existing encryption pattern
- Add timeout to IMAP4_SSL connection to prevent indefinite hangs
- Log exceptions during IMAP cleanup instead of silently swallowing them
- Add unit tests for check_imap_bounces with mocked IMAP server (5 tests, all passing)
@Shiva210Jyoti

Copy link
Copy Markdown
Author

@CodeRabbit @Kuldeeep18 All CodeRabbit review comments addressed:

  • imap_password now encrypted using the project's existing encryption pattern
  • Added 30s timeout to IMAP connection to prevent worker hangs
  • Cleanup exceptions now logged instead of silently swallowed
  • Added 5 unit tests covering bounce parsing, error isolation, and message flagging — all passing

Ready for your review!

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get PR details and review comments
gh pr view 299 --repo Kuldeeep18/LeadOrbit --json title,state,reviews,comments

# Get review comments (inline)
gh api repos/Kuldeeep18/LeadOrbit/pulls/299/comments --jq '[.[] | {id, body, path, line, user: .user.login, resolved: .resolved}]' 2>/dev/null | head -200

# Get issue comments
gh api repos/Kuldeeep18/LeadOrbit/issues/299/comments --jq '[.[] | {id, body: .body[:300], user: .user.login}]' 2>/dev/null | head -200

Length of output: 34851



@Shiva210Jyoti Thanks for the thorough update! I can confirm all three previously raised issues are marked as resolved in commit 4f78183:

  • imap_password plaintext storage — encrypted using the project's custom encryption pattern (encryption.py / fields.py)
  • Missing IMAP connection timeout — 30s timeout added to IMAP4_SSL
  • Silent cleanup exceptions — now logged at debug/warning level

A new review is currently being processed for the updated push (covering encryption.py, fields.py, the new migration 0010_encrypt_imap_password.py, tests.py, and requirements.txt). I'll complete that shortly.

One thing to be aware of ahead of merge: the Docstring Coverage pre-merge check is currently failing at 22.22% against the required 80% threshold. You may want to add docstrings to the new functions in tasks.py (e.g., check_imap_bounces, the helper functions) and the new encryption.py/fields.py modules to bring that up.

(◕‿◕✿) 🐇

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- Add docstrings to all helper functions in check_imap_bounces flow
- Add docstrings to encryption.py and fields.py
- Add class docstring to ConnectedEmailAccount

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
backend/campaigns/fields.py (1)

22-24: 💤 Low value

Prefix unused variable with underscore to satisfy linter.

Ruff flags path as unpacked but unused.

♻️ Suggested fix
     def deconstruct(self):
-        name, path, args, kwargs = super().deconstruct()
+        name, _path, args, kwargs = super().deconstruct()
         return name, 'campaigns.fields.EncryptedTextField', args, kwargs
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/campaigns/fields.py` around lines 22 - 24, The deconstruct method in
the EncryptedTextField class unpacks the path variable from the
super().deconstruct() call but never uses it, which causes the Ruff linter to
flag it as unused. Prefix the unused path variable with an underscore (change it
to _path) in the unpacking statement to indicate that it is intentionally unused
and satisfy the linter.

Source: Linters/SAST tools

backend/campaigns/encryption.py (1)

9-18: 💤 Low value

Consider validating key format at module load time.

If FIELD_ENCRYPTION_KEY is set but malformed (not a valid URL-safe base64-encoded 32-byte key), Fernet will raise ValueError on first use rather than at startup. This could cause cryptic runtime failures during the first encrypt/decrypt call.

♻️ Optional: Add early key validation
 def _get_fernet_key_bytes():
     configured = (getattr(settings, 'FIELD_ENCRYPTION_KEY', '') or '').strip()
     if configured:
-        return configured.encode('utf-8')
+        key_bytes = configured.encode('utf-8')
+        # Validate key format early to fail fast on misconfiguration
+        try:
+            Fernet(key_bytes)
+        except ValueError as e:
+            raise ImproperlyConfigured(
+                f'FIELD_ENCRYPTION_KEY is invalid: {e}. '
+                'Generate one with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"'
+            )
+        return key_bytes
     if settings.DEBUG:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/campaigns/encryption.py` around lines 9 - 18, The
_get_fernet_key_bytes function returns encryption keys without validating their
format, which causes Fernet to raise ValueError on first encrypt/decrypt call if
the key is malformed. Add validation in the _get_fernet_key_bytes function to
verify that the returned key is a valid Fernet-compatible key (a 32-byte
URL-safe base64-encoded string) by attempting to instantiate a Fernet object
with it and catching any ValueError to provide a clear ImproperlyConfigured
error at module load time instead of allowing cryptic runtime failures later.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/campaigns/migrations/0010_encrypt_imap_password.py`:
- Around line 22-28: The operations list has the wrong order, causing double
encryption of the imap_password field. The AlterField operation converts the
field to EncryptedTextField before RunPython executes, so when account.save() is
called in encrypt_existing_imap_passwords, Django's get_prep_value()
automatically encrypts the already-encrypted value. Swap the order of the two
operations in the operations list so that
migrations.RunPython(encrypt_existing_imap_passwords, migrations.RunPython.noop)
runs first (while the field is still plain TextField), and migrations.AlterField
runs second (after manual encryption is complete).

In `@requirements.txt`:
- Line 16: The cryptography package is pinned to version 43.x which contains
multiple unpatched security vulnerabilities (GHSA-537c-gmf6-5ccf,
GHSA-r6ph-v2qm-q3c2, and others). Update the version constraint in the
cryptography dependency to use a current stable version that includes these
security patches, such as version 49.0.0 or later, to ensure the application is
protected against these known vulnerabilities.

---

Nitpick comments:
In `@backend/campaigns/encryption.py`:
- Around line 9-18: The _get_fernet_key_bytes function returns encryption keys
without validating their format, which causes Fernet to raise ValueError on
first encrypt/decrypt call if the key is malformed. Add validation in the
_get_fernet_key_bytes function to verify that the returned key is a valid
Fernet-compatible key (a 32-byte URL-safe base64-encoded string) by attempting
to instantiate a Fernet object with it and catching any ValueError to provide a
clear ImproperlyConfigured error at module load time instead of allowing cryptic
runtime failures later.

In `@backend/campaigns/fields.py`:
- Around line 22-24: The deconstruct method in the EncryptedTextField class
unpacks the path variable from the super().deconstruct() call but never uses it,
which causes the Ruff linter to flag it as unused. Prefix the unused path
variable with an underscore (change it to _path) in the unpacking statement to
indicate that it is intentionally unused and satisfy the linter.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 87a684f2-33f9-49c2-be0d-d9f7c182620a

📥 Commits

Reviewing files that changed from the base of the PR and between fbf56d0 and 4f78183.

📒 Files selected for processing (9)
  • backend/backend/settings.py
  • backend/campaigns/encryption.py
  • backend/campaigns/fields.py
  • backend/campaigns/migrations/0010_encrypt_imap_password.py
  • backend/campaigns/models.py
  • backend/campaigns/tasks.py
  • backend/campaigns/tests.py
  • backend/db.sqlite3
  • requirements.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/backend/settings.py
  • backend/campaigns/models.py

Comment thread backend/campaigns/migrations/0010_encrypt_imap_password.py Outdated
Comment thread requirements.txt Outdated
@Shiva210Jyoti

Copy link
Copy Markdown
Author

@coderabbitai Added docstrings to all new functions to address the docstring coverage check. Ready for re-review.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

@Shiva210Jyoti Great work adding docstrings across tasks.py, encryption.py, and fields.py! Triggering a fresh review now to verify coverage and check the latest changes. 🐇✨

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- Swap migration order so passwords are encrypted before AlterField, fixing double-encryption bug
- Use queryset.update() to bypass model save hooks during migration
- Upgrade cryptography to >=49.0,<50.0 to address known vulnerabilities in 43.x
@Shiva210Jyoti

Copy link
Copy Markdown
Author

@coderabbitai
Fixed both remaining issues:

  • Corrected migration operation order to encrypt passwords before converting the field type, fixing the double-encryption bug
  • Upgraded cryptography to >=49.0,<50.0 to address known vulnerabilities

All 5 tests still passing. Ready for re-review 🙏

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

@Shiva210Jyoti Great progress! Both fixes look important:

  • Migration operation order — encrypting before altering the field type is the correct sequence; this prevents the double-encryption issue where already-encrypted values would have been encrypted again.
  • cryptography version bump — upgrading to >=49.0,<50.0 addresses known CVEs in older releases.

Triggering a fresh review now to verify the latest changes. 🐇✨

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/campaigns/models.py (1)

33-33: ⚠️ Potential issue | 🟡 Minor

Constrain imap_port to valid TCP port values.

IntegerField accepts 0, negatives, and values above 65535, which will cause imaplib.IMAP4_SSL() to fail when the periodic IMAP bounce check (check_imap_bounces task) attempts to connect. Add range validation via PositiveIntegerField with explicit validators and generate a new migration to update the existing field.

Proposed fix
 from django.db import models
 from django.conf import settings
+from django.core.validators import MaxValueValidator, MinValueValidator
 from tenants.models import TenantModel
 from leads.models import Lead
 from .fields import EncryptedTextField
 import uuid
@@
-    imap_port = models.IntegerField(default=993)
+    imap_port = models.PositiveIntegerField(
+        default=993,
+        validators=[MinValueValidator(1), MaxValueValidator(65535)],
+    )

Ensure the migration includes the field type and validator changes. Consider adding a DB CheckConstraint for additional safety if any code path bypasses ORM validation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/campaigns/models.py` at line 33, The imap_port field in the Campaign
model uses IntegerField which accepts invalid port values (negatives, zero, and
values above 65535) that will cause imaplib.IMAP4_SSL() to fail when the
check_imap_bounces task attempts to connect. Replace the IntegerField with
PositiveIntegerField for the imap_port field and add explicit validators such as
MaxValueValidator to ensure the port does not exceed 65535. After making the
field definition change, generate a new database migration that captures the
field type change and validator additions. Additionally, consider adding a
database-level CheckConstraint to the model's Meta class for extra safety
against values that might bypass ORM validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/campaigns/fields.py`:
- Line 54: In the deconstruct method where super().deconstruct() is called, the
unpacked path variable is intentionally ignored because a hardcoded field path
is returned instead. Prefix this variable with an underscore by changing path to
_path in the tuple unpacking to indicate it is intentionally discarded and
satisfy the Ruff RUF059 lint rule.

---

Outside diff comments:
In `@backend/campaigns/models.py`:
- Line 33: The imap_port field in the Campaign model uses IntegerField which
accepts invalid port values (negatives, zero, and values above 65535) that will
cause imaplib.IMAP4_SSL() to fail when the check_imap_bounces task attempts to
connect. Replace the IntegerField with PositiveIntegerField for the imap_port
field and add explicit validators such as MaxValueValidator to ensure the port
does not exceed 65535. After making the field definition change, generate a new
database migration that captures the field type change and validator additions.
Additionally, consider adding a database-level CheckConstraint to the model's
Meta class for extra safety against values that might bypass ORM validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 52ecf859-229c-4e82-8bcf-3804809e95fe

📥 Commits

Reviewing files that changed from the base of the PR and between 4f78183 and 28054b6.

📒 Files selected for processing (4)
  • backend/campaigns/encryption.py
  • backend/campaigns/fields.py
  • backend/campaigns/models.py
  • backend/campaigns/tasks.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/campaigns/tasks.py
  • backend/campaigns/encryption.py

Comment thread backend/campaigns/fields.py Outdated
@Shiva210Jyoti

Copy link
Copy Markdown
Author

@Kuldeeep18 kindly review the PR,all coderabbitai requirements have been met.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LO-032 [Hard]: Automatic IMAP Email Bounce Parser

2 participants