Skip to content

Add MSG to EML email conversion support (#367) #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 24, 2025

Conversation

gingeekrishna
Copy link
Contributor

@gingeekrishna gingeekrishna commented Jul 24, 2025

  • Add new msgconvert converter using libemail-outlook-message-perl
  • Support conversion from Outlook MSG files to standard EML format
  • Add msgconvert to Docker dependencies and version checking
  • Register msgconvert converter in main converter registry

Implements feature request #367 for email format conversion

Summary by Sourcery

Add support for converting Outlook MSG files to standard EML format using the msgconvert tool.

New Features:

  • Implement a msgconvert converter for .msg to .eml conversion
  • Register msgconvert in the main converter registry

Enhancements:

  • Print msgconvert version in the version summary output

Build:

  • Install libemail-outlook-message-perl in the Dockerfile for msgconvert support

- Add new msgconvert converter using libemail-outlook-message-perl
- Support conversion from Outlook MSG files to standard EML format
- Add msgconvert to Docker dependencies and version checking
- Register msgconvert converter in main converter registry

Implements feature request C4illin#367 for email format conversion
Copy link
Contributor

sourcery-ai bot commented Jul 24, 2025

Reviewer's Guide

This PR implements Outlook MSG to EML conversion by integrating the Perl-based msgconvert tool: it adds a new converter module with execution logic, registers it in the main registry, ensures the tool is installed in Docker, and surfaces its version in the printVersions helper.

Sequence diagram for MSG to EML conversion process

sequenceDiagram
    participant User
    participant ConverterRegistry
    participant msgconvert_module as msgconvert
    participant msgconvert_tool as msgconvert (CLI)
    User->>ConverterRegistry: Request conversion (MSG to EML)
    ConverterRegistry->>msgconvert: Call convert()
    msgconvert->>msgconvert_tool: Execute msgconvert CLI
    msgconvert_tool-->>msgconvert: Conversion result
    msgconvert-->>ConverterRegistry: Done
    ConverterRegistry-->>User: Conversion complete
Loading

Class diagram for updated converter registry in main.ts

classDiagram
    class ConverterRegistry {
        +pandoc
        +msgconvert
        +dvisvgm
        ...
    }
    class msgconvert {
        +properties
        +convert()
    }
    ConverterRegistry --> msgconvert : registers
Loading

File-Level Changes

Change Details Files
Added a new msgconvert-based converter for MSG→EML
  • Created conversion module with execFile logic
  • Defined from/to email format properties
  • Handled success/error output and promise resolution
src/converters/msgconvert.ts
Registered msgconvert in the converter registry
  • Added msgconvert entry alongside other converters
  • Linked to propertiesMsgconvert and convertMsgconvert functions
src/converters/main.ts
Extended Docker setup to include msgconvert dependency
  • Installed libemail-outlook-message-perl via apt-get
Dockerfile
Updated version reporting to include msgconvert
  • Executed msgconvert --version
  • Logged version or installation error to console
src/helpers/printVersions.ts

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @gingeekrishna - I've reviewed your changes - here's some feedback:

  • Align the export names in msgconvert.ts with how you import them in main.ts (e.g. export convertMsgconvert or adjust the registry import) to avoid naming mismatches.
  • Improve error handling by rejecting with Error objects (instead of plain strings) and resolving with the actual output file path rather than a static "Done" message for better downstream usage.
  • Consider extracting the execFile promise-handling boilerplate into a shared helper to reduce duplication across converters and simplify future additions.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Align the export names in msgconvert.ts with how you import them in main.ts (e.g. export convertMsgconvert or adjust the registry import) to avoid naming mismatches.
- Improve error handling by rejecting with Error objects (instead of plain strings) and resolving with the actual output file path rather than a static "Done" message for better downstream usage.
- Consider extracting the execFile promise-handling boilerplate into a shared helper to reduce duplication across converters and simplify future additions.

## Individual Comments

### Comment 1
<location> `src/converters/msgconvert.ts:33` </location>
<code_context>
+          return;
+        }
+
+        if (stdout) {
+          console.log(`stdout: ${stdout}`);
+        }
+
</code_context>

<issue_to_address>
Logging stdout may be unnecessary and could clutter output.

If there's no specific reason to log msgconvert's stdout, please remove this console.log to keep production output clean.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        if (stdout) {
          console.log(`stdout: ${stdout}`);
        }
=======
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `src/converters/msgconvert.ts:37` </location>
<code_context>
+          console.log(`stdout: ${stdout}`);
+        }
+
+        if (stderr) {
+          console.error(`stderr: ${stderr}`);
+        }
+
</code_context>

<issue_to_address>
Logging stderr directly may expose internal details.

Consider logging stderr conditionally or sanitizing its content to avoid exposing sensitive information.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        if (stderr) {
          console.error(`stderr: ${stderr}`);
        }
=======
        if (stderr) {
          // Sanitize stderr to avoid exposing sensitive information
          const sanitizedStderr = stderr.replace(/(\/[^\s]+)/g, "[REDACTED_PATH]");
          // Optionally, log a generic message or the sanitized content
          console.error(`stderr: ${sanitizedStderr.length > 200 ? sanitizedStderr.slice(0, 200) + '...' : sanitizedStderr}`);
        }
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `src/converters/msgconvert.ts:41` </location>
<code_context>
+          console.error(`stderr: ${stderr}`);
+        }
+
+        resolve("Done");
+      });
+    } else {
</code_context>

<issue_to_address>
Returning a static string on success may be limiting.

Consider returning targetPath or relevant result data instead to provide more useful context for callers and improve future flexibility.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        resolve("Done");
=======
        resolve(targetPath);
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 33 to 35
if (stdout) {
console.log(`stdout: ${stdout}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Logging stdout may be unnecessary and could clutter output.

If there's no specific reason to log msgconvert's stdout, please remove this console.log to keep production output clean.

Suggested change
if (stdout) {
console.log(`stdout: ${stdout}`);
}

Comment on lines 37 to 39
if (stderr) {
console.error(`stderr: ${stderr}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🚨 suggestion (security): Logging stderr directly may expose internal details.

Consider logging stderr conditionally or sanitizing its content to avoid exposing sensitive information.

Suggested change
if (stderr) {
console.error(`stderr: ${stderr}`);
}
if (stderr) {
// Sanitize stderr to avoid exposing sensitive information
const sanitizedStderr = stderr.replace(/(\/[^\s]+)/g, "[REDACTED_PATH]");
// Optionally, log a generic message or the sanitized content
console.error(`stderr: ${sanitizedStderr.length > 200 ? sanitizedStderr.slice(0, 200) + '...' : sanitizedStderr}`);
}

- Remove unnecessary stdout logging to reduce output clutter
- Sanitize stderr logging to protect sensitive path information
- Return targetPath instead of generic 'Done' message for better caller context
- Use proper Error objects instead of string rejections
- Address Sourcery AI feedback from PR C4illin#370
@C4illin C4illin merged commit 8f93ac2 into C4illin:main Jul 24, 2025
1 of 3 checks passed
@C4illin
Copy link
Owner

C4illin commented Jul 24, 2025

Thanks for this!

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.

2 participants