-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Lombiq/issue/OFFI-134
OFFI-134: Add email client with IMAP email download, background sync and content types
- Loading branch information
Showing
35 changed files
with
1,056 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
name: Validate NuGet Publish | ||
|
||
on: | ||
pull_request: | ||
push: | ||
branches: | ||
- dev | ||
|
||
jobs: | ||
validate-nuget-publish: | ||
name: Validate NuGet Publish | ||
uses: Lombiq/GitHub-Actions/.github/workflows/validate-nuget-publish.yml@dev | ||
# Temporarily commented out until making it a fully compliant OSS module. | ||
## on: | ||
## pull_request: | ||
## push: | ||
## branches: | ||
## - dev | ||
## | ||
## jobs: | ||
## validate-nuget-publish: | ||
## name: Validate NuGet Publish | ||
## uses: Lombiq/GitHub-Actions/.github/workflows/validate-nuget-publish.yml@dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace Lombiq.EmailClient.Constants; | ||
|
||
public static class FeatureIds | ||
{ | ||
public const string Area = "Lombiq.EmailClient"; | ||
|
||
public const string Default = Area; | ||
public const string Imap = Area + "." + nameof(Imap); | ||
public const string EmailSync = Area + "." + nameof(EmailSync); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Lombiq.EmailClient.Constants; | ||
|
||
public static class Protocols | ||
{ | ||
public const string Imap = "IMAP"; | ||
} |
53 changes: 53 additions & 0 deletions
53
Lombiq.EmailClient/Drivers/EmailSyncSettingsDisplayDriver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using Lombiq.EmailClient.Models; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Http; | ||
using OrchardCore.DisplayManagement.Entities; | ||
using OrchardCore.DisplayManagement.Handlers; | ||
using OrchardCore.DisplayManagement.Views; | ||
using OrchardCore.Settings; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace Lombiq.EmailClient.Drivers; | ||
|
||
public class EmailSyncSettingsDisplayDriver : SiteDisplayDriver<EmailSyncSettings> | ||
{ | ||
public const string GroupId = nameof(EmailSyncSettings); | ||
|
||
private readonly IAuthorizationService _authorizationService; | ||
private readonly IHttpContextAccessor _hca; | ||
|
||
protected override string SettingsGroupId => GroupId; | ||
|
||
public EmailSyncSettingsDisplayDriver(IAuthorizationService authorizationService, IHttpContextAccessor hca) | ||
{ | ||
_authorizationService = authorizationService; | ||
_hca = hca; | ||
} | ||
|
||
public override async Task<IDisplayResult> EditAsync(ISite model, EmailSyncSettings section, BuildEditorContext context) | ||
{ | ||
if (!await AuthorizeAsync(context)) return null; | ||
|
||
return Initialize<EmailSyncSettings>($"{nameof(EmailSyncSettings)}_Edit", section.CopyTo) | ||
.PlaceInContent() | ||
.OnGroup(GroupId); | ||
} | ||
|
||
public override async Task<IDisplayResult> UpdateAsync(ISite model, EmailSyncSettings section, UpdateEditorContext context) | ||
{ | ||
if (await AuthorizeAsync(context) && | ||
await context.CreateModelAsync<EmailSyncSettings>(Prefix) is { } viewModel) | ||
{ | ||
viewModel.CopyTo(section); | ||
} | ||
|
||
return await EditAsync(model, section, context); | ||
} | ||
|
||
private Task<bool> AuthorizeAsync(BuildEditorContext context) => | ||
_hca.HttpContext?.User is { } user && | ||
context.GroupId.EqualsOrdinalIgnoreCase(GroupId) | ||
? _authorizationService.AuthorizeAsync(user, Permissions.EmailSyncPermissions.ManageEmailSyncSettings) | ||
: Task.FromResult(false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using Lombiq.EmailClient.Models; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Http; | ||
using OrchardCore.DisplayManagement.Entities; | ||
using OrchardCore.DisplayManagement.Handlers; | ||
using OrchardCore.DisplayManagement.Views; | ||
using OrchardCore.Settings; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace Lombiq.EmailClient.Drivers; | ||
|
||
public class ImapSettingsDisplayDriver : SiteDisplayDriver<ImapSettings> | ||
{ | ||
public const string GroupId = nameof(ImapSettings); | ||
|
||
private readonly IAuthorizationService _authorizationService; | ||
private readonly IHttpContextAccessor _hca; | ||
|
||
protected override string SettingsGroupId => GroupId; | ||
|
||
public ImapSettingsDisplayDriver(IAuthorizationService authorizationService, IHttpContextAccessor hca) | ||
{ | ||
_authorizationService = authorizationService; | ||
_hca = hca; | ||
} | ||
|
||
public override async Task<IDisplayResult> EditAsync(ISite model, ImapSettings section, BuildEditorContext context) | ||
{ | ||
if (!await AuthorizeAsync(context)) return null; | ||
|
||
return Initialize<ImapSettings>($"{nameof(ImapSettings)}_Edit", section.CopyTo) | ||
.PlaceInContent() | ||
.OnGroup(GroupId); | ||
} | ||
|
||
public override async Task<IDisplayResult> UpdateAsync(ISite model, ImapSettings section, UpdateEditorContext context) | ||
{ | ||
if (await AuthorizeAsync(context) && | ||
await context.CreateModelAsync<ImapSettings>(Prefix) is { } viewModel) | ||
{ | ||
viewModel.CopyTo(section); | ||
} | ||
|
||
return await EditAsync(model, section, context); | ||
} | ||
|
||
private Task<bool> AuthorizeAsync(BuildEditorContext context) => | ||
_hca.HttpContext?.User is { } user && | ||
context.GroupId.EqualsOrdinalIgnoreCase(GroupId) | ||
? _authorizationService.AuthorizeAsync(user, Permissions.ImapPermissions.ManageImapSettings) | ||
: Task.FromResult(false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Razor"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> | ||
<DefaultItemExcludes>$(DefaultItemExcludes);.git*;node_modules\**</DefaultItemExcludes> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<Title>Lombiq Email Client for Orchard Core</Title> | ||
<Authors>Lombiq Technologies</Authors> | ||
<Copyright>Copyright © 2025, Lombiq Technologies Ltd.</Copyright> | ||
<Description>Lombiq Email Client for Orchard Core: With the help of this module, you can do advanced email operations such as downloading them using IMAP.</Description> | ||
<PackageIcon>NuGetIcon.png</PackageIcon> | ||
<PackageTags>OrchardCore;Lombiq;AspNetCore;Email;IMAP</PackageTags> | ||
<RepositoryUrl>https://github.com/Lombiq/Orchard-Email-Client</RepositoryUrl> | ||
<PackageProjectUrl>https://github.com/Lombiq/Orchard-Email-Client/blob/dev/Readme.md</PackageProjectUrl> | ||
<PackageLicenseExpression>BSD-3-Clause</PackageLicenseExpression> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Remove="node_modules\**" /> | ||
<None Include="../Readme.md" Link="Readme.md" /> | ||
<None Include="NuGetIcon.png" Pack="true" PackagePath="" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="MailKit" Version="4.9.0" /> | ||
<PackageReference Include="OrchardCore.Module.Targets" Version="2.1.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="'$(NuGetBuild)' != 'true'"> | ||
<ProjectReference Include="..\..\..\Libraries\Lombiq.HelpfulLibraries\Lombiq.HelpfulLibraries.OrchardCore\Lombiq.HelpfulLibraries.OrchardCore.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="'$(NuGetBuild)' == 'true'"> | ||
<PackageReference Include="Lombiq.HelpfulLibraries.OrchardCore" Version="12.0.0" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using OrchardCore.Modules.Manifest; | ||
using static Lombiq.EmailClient.Constants.FeatureIds; | ||
|
||
[assembly: Module( | ||
Name = "Lombiq Email Client", | ||
Author = "Lombiq Technologies", | ||
Website = "https://github.com/Lombiq/Orchard-Email-Client", | ||
Version = "0.0.1" | ||
)] | ||
|
||
[assembly: Feature( | ||
Id = Default, | ||
Name = "Lombiq Email Client - Base", | ||
Category = "Email", | ||
Description = "Base functionality for the email client such as content types. Should be used along with a " + | ||
"specific email provider feature (e.g., IMAP).", | ||
EnabledByDependencyOnly = true | ||
)] | ||
|
||
[assembly: Feature( | ||
Id = Imap, | ||
Name = "Lombiq Email Client - IMAP", | ||
Category = "Email", | ||
Description = "IMAP email provider for the email client.", | ||
Dependencies = | ||
[ | ||
Default, | ||
] | ||
)] | ||
|
||
[assembly: Feature( | ||
Id = EmailSync, | ||
Name = "Lombiq Email Client - Email Sync", | ||
Category = "Email", | ||
Description = "Syncs emails from an email provider periodically.", | ||
Dependencies = | ||
[ | ||
Default, | ||
] | ||
)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System.Net.Mime; | ||
|
||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents metadata for an attachment, such as its file name, MIME type, and size. | ||
/// </summary> | ||
public class AttachmentMetadata | ||
{ | ||
/// <summary> | ||
/// Gets or sets the file name of the attachment. | ||
/// </summary> | ||
public string FileName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the MIME type of the attachment (e.g., <see cref="MediaTypeNames.Application.Pdf"/>). | ||
/// </summary> | ||
public string MimeType { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the size of the attachment in bytes. | ||
/// </summary> | ||
public long? Size { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents an email address with a display name and the actual address. | ||
/// </summary> | ||
public class EmailAddress | ||
{ | ||
/// <summary> | ||
/// Gets or sets the display name of the email address (e.g., "John Doe"). | ||
/// </summary> | ||
public string DisplayName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the actual email address (e.g., "[email protected]"). | ||
/// </summary> | ||
public string Address { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents the body of an email, including its content and format. | ||
/// </summary> | ||
public class EmailBody | ||
{ | ||
/// <summary> | ||
/// Gets or sets the main body of the email as plain text or HTML. | ||
/// </summary> | ||
public string Body { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets a value indicating whether the body contains HTML content. | ||
/// </summary> | ||
public bool IsHtml { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents the content of an email, including its body and attachments. | ||
/// </summary> | ||
public class EmailContent | ||
{ | ||
/// <summary> | ||
/// Gets or sets the body of the email, including its content and format information. | ||
/// </summary> | ||
public EmailBody Body { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the metadata of the attachments associated with this email. | ||
/// </summary> | ||
public IList<AttachmentMetadata> Attachments { get; private set; } = []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Lombiq.EmailClient.Models; | ||
|
||
public class EmailFilterParameters | ||
{ | ||
public string Subject { get; set; } | ||
public uint AfterImapUniqueId { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents the headers of an email, including sender, recipients, subject, and dates. | ||
/// </summary> | ||
public class EmailHeader | ||
{ | ||
/// <summary> | ||
/// Gets or sets the subject line of the email. | ||
/// </summary> | ||
public string Subject { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the sender of the email, including their display name and email address. | ||
/// </summary> | ||
public EmailAddress Sender { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the primary recipients of the email (To field). | ||
/// </summary> | ||
public IList<EmailAddress> To { get; private set; } = []; | ||
|
||
/// <summary> | ||
/// Gets the carbon copy recipients of the email (Cc field). | ||
/// </summary> | ||
public IList<EmailAddress> Cc { get; private set; } = []; | ||
|
||
/// <summary> | ||
/// Gets the blind carbon copy recipients of the email (Bcc field). | ||
/// </summary> | ||
public IList<EmailAddress> Bcc { get; private set; } = []; | ||
|
||
/// <summary> | ||
/// Gets or sets the date and time when the email was sent by the sender's client. | ||
/// This value is in UTC but reflects the sender's system clock and timezone. | ||
/// </summary> | ||
public DateTime? SentDateUtc { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
namespace Lombiq.EmailClient.Models; | ||
|
||
/// <summary> | ||
/// Represents the metadata, headers, and content of an email, including protocol-specific details, | ||
/// sender and recipient information, and message body. | ||
/// </summary> | ||
public class EmailMessage | ||
{ | ||
/// <summary> | ||
/// Gets or sets the protocol-specific metadata of the email (e.g., Message-ID, protocol name, and folder information). | ||
/// </summary> | ||
public EmailMetadata Metadata { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the headers of the email, including sender, recipients, and subject. | ||
/// </summary> | ||
public EmailHeader Header { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the content of the email, including its body and format details. | ||
/// This is populated only after the email is downloaded. | ||
/// </summary> | ||
public EmailContent Content { get; set; } | ||
} |
Oops, something went wrong.