mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-11 15:26:55 +03:00
Add Thunderbird email support for Linux
On Windows this should already work through MAPI, but Linux doesn't have a standard email api.
This commit is contained in:
parent
072f092a98
commit
50e12c4dc4
@ -22,6 +22,8 @@ public class AutofacEmailProviderFactory : IEmailProviderFactory
|
||||
return _container.Resolve<GmailEmailProvider>();
|
||||
case EmailProviderType.OutlookWeb:
|
||||
return _container.Resolve<OutlookWebEmailProvider>();
|
||||
case EmailProviderType.Thunderbird:
|
||||
return _container.Resolve<ThunderbirdEmailProvider>();
|
||||
default:
|
||||
return _container.Resolve<MapiEmailProvider>();
|
||||
}
|
||||
|
@ -13,17 +13,20 @@ public class EmailProviderForm : EtoDialogBase
|
||||
private readonly SystemEmailClients _systemEmailClients;
|
||||
private readonly GmailOauthProvider _gmailOauthProvider;
|
||||
private readonly OutlookWebOauthProvider _outlookWebOauthProvider;
|
||||
private readonly ThunderbirdEmailProvider _thunderbirdProvider;
|
||||
|
||||
private readonly List<EmailProviderWidget> _providerWidgets;
|
||||
private readonly string[] _systemClientNames;
|
||||
private readonly string? _defaultSystemClientName;
|
||||
|
||||
public EmailProviderForm(Naps2Config config, SystemEmailClients systemEmailClients,
|
||||
GmailOauthProvider gmailOauthProvider, OutlookWebOauthProvider outlookWebOauthProvider) : base(config)
|
||||
GmailOauthProvider gmailOauthProvider, OutlookWebOauthProvider outlookWebOauthProvider,
|
||||
ThunderbirdEmailProvider thunderbirdProvider) : base(config)
|
||||
{
|
||||
_systemEmailClients = systemEmailClients;
|
||||
_gmailOauthProvider = gmailOauthProvider;
|
||||
_outlookWebOauthProvider = outlookWebOauthProvider;
|
||||
_thunderbirdProvider = thunderbirdProvider;
|
||||
|
||||
_providerWidgets = new List<EmailProviderWidget>();
|
||||
#if NET6_0_OR_GREATER
|
||||
@ -52,6 +55,21 @@ public class EmailProviderForm : EtoDialogBase
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
}
|
||||
|
||||
// For Windows we expect Thunderbird to be used through MAPI. For Linux we need to handle it specially.
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
_providerWidgets.Add(new EmailProviderWidget
|
||||
{
|
||||
ProviderType = EmailProviderType.Thunderbird,
|
||||
ProviderIcon = Icons.thunderbird.ToEtoImage(),
|
||||
ProviderName = EmailProviderType.Thunderbird.Description(),
|
||||
ClickAction = ChooseThunderbird,
|
||||
// When Thunderbird isn't available, we disable it rather than hide it.
|
||||
// The point is to give a hint to the user that Thunderbird support is present.
|
||||
Enabled = _thunderbirdProvider.IsAvailable
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_gmailOauthProvider.HasClientCreds)
|
||||
@ -105,7 +123,8 @@ public class EmailProviderForm : EtoDialogBase
|
||||
_providerWidgets.Select(x => C.Button(new ActionCommand(x.ClickAction)
|
||||
{
|
||||
Text = x.ProviderName,
|
||||
Image = x.ProviderIcon
|
||||
Image = x.ProviderIcon,
|
||||
Enabled = x.Enabled
|
||||
}, ButtonImagePosition.Left, big: true).NaturalWidth(500).Height(50)).Expand()
|
||||
);
|
||||
}
|
||||
@ -123,6 +142,16 @@ public class EmailProviderForm : EtoDialogBase
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ChooseThunderbird()
|
||||
{
|
||||
var transact = Config.User.BeginTransaction();
|
||||
transact.Remove(c => c.EmailSetup);
|
||||
transact.Set(c => c.EmailSetup.ProviderType, EmailProviderType.Thunderbird);
|
||||
transact.Commit();
|
||||
Result = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ChooseOauth(OauthProvider provider)
|
||||
{
|
||||
var authForm = FormFactory.Create<AuthorizeForm>();
|
||||
@ -167,5 +196,6 @@ public class EmailProviderForm : EtoDialogBase
|
||||
public required Bitmap ProviderIcon { get; init; }
|
||||
public required string ProviderName { get; init; }
|
||||
public required Action ClickAction { get; init; }
|
||||
public bool Enabled { get; set; } = true;
|
||||
}
|
||||
}
|
10
NAPS2.Lib/Icons.Designer.cs
generated
10
NAPS2.Lib/Icons.Designer.cs
generated
@ -609,6 +609,16 @@ namespace NAPS2 {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] thunderbird {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("thunderbird", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -346,6 +346,9 @@
|
||||
<data name="outlookweb" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Icons\outlookweb.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="thunderbird" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Icons\thunderbird.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="email_setting" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Icons\email_setting.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
|
BIN
NAPS2.Lib/Icons/thunderbird.png
Executable file
BIN
NAPS2.Lib/Icons/thunderbird.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
@ -10,5 +10,7 @@ public enum EmailProviderType
|
||||
[LocalizedDescription(typeof(SettingsResources), "EmailProviderType_Gmail")]
|
||||
Gmail,
|
||||
[LocalizedDescription(typeof(SettingsResources), "EmailProviderType_OutlookWeb")]
|
||||
OutlookWeb
|
||||
OutlookWeb,
|
||||
[LocalizedDescription(typeof(SettingsResources), "EmailProviderType_Thunderbird")]
|
||||
Thunderbird
|
||||
}
|
92
NAPS2.Lib/ImportExport/Email/ThunderbirdEmailProvider.cs
Normal file
92
NAPS2.Lib/ImportExport/Email/ThunderbirdEmailProvider.cs
Normal file
@ -0,0 +1,92 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NAPS2.ImportExport.Email;
|
||||
|
||||
public class ThunderbirdEmailProvider : IEmailProvider
|
||||
{
|
||||
private readonly ErrorOutput _errorOutput;
|
||||
|
||||
public ThunderbirdEmailProvider(ErrorOutput errorOutput)
|
||||
{
|
||||
_errorOutput = errorOutput;
|
||||
}
|
||||
|
||||
// Note we can't really support the Flatpak version of Thunderbird as it won't have access to attachment files from
|
||||
// the sandbox.
|
||||
public bool IsAvailable => ProcessHelper.IsSuccessful("thunderbird", "-v", 1000);
|
||||
|
||||
public Task<bool> SendEmail(EmailMessage message, ProgressHandler progress = default)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
var arguments = new List<string>();
|
||||
string? bodyFile = null;
|
||||
try
|
||||
{
|
||||
if (message.Attachments.Any())
|
||||
{
|
||||
// TODO: Need to use name if different than path (i.e. copy to temp)
|
||||
arguments.Add($"attachment='{string.Join(",", message.Attachments.Select(x => x.FilePath))}'");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(message.BodyText))
|
||||
{
|
||||
bodyFile = Path.Combine(Paths.Temp, Path.GetRandomFileName() + ".txt");
|
||||
await File.WriteAllTextAsync(bodyFile, message.BodyText, Encoding.UTF8);
|
||||
arguments.Add($"message='{bodyFile}'");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(message.Subject))
|
||||
{
|
||||
// There doesn't seem to be a way to escape "'," but it shouldn't be common
|
||||
arguments.Add($"subject='{message.Subject.Replace("',", "' ,")}'");
|
||||
}
|
||||
if (message.Recipients.Any(x => x.Type == EmailRecipientType.To))
|
||||
{
|
||||
arguments.Add(
|
||||
$"to='{string.Join(",", message.Recipients.Where(x => x.Type == EmailRecipientType.To).Select(x => x.Address))}'");
|
||||
}
|
||||
if (message.Recipients.Any(x => x.Type == EmailRecipientType.Cc))
|
||||
{
|
||||
arguments.Add(
|
||||
$"cc='{string.Join(",", message.Recipients.Where(x => x.Type == EmailRecipientType.Cc).Select(x => x.Address))}'");
|
||||
}
|
||||
if (message.Recipients.Any(x => x.Type == EmailRecipientType.Bcc))
|
||||
{
|
||||
arguments.Add(
|
||||
$"bcc='{string.Join(",", message.Recipients.Where(x => x.Type == EmailRecipientType.Bcc).Select(x => x.Address))}'");
|
||||
}
|
||||
// This escaping isn't perfect but it should be good enough. I can't identify clear rules used by the
|
||||
// thunderbird parser anyway.
|
||||
var composeArgs = string.Join(",", arguments.Select(x => x.Replace("\"", "\\\"")));
|
||||
Console.WriteLine(composeArgs);
|
||||
var process =
|
||||
Process.Start(new ProcessStartInfo("thunderbird", $"-compose \"{composeArgs}\"")
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
});
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorOutput.DisplayError(MiscResources.EmailError, ex);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (bodyFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(bodyFile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
407
NAPS2.Lib/Lang/Resources/SettingsResources.Designer.cs
generated
407
NAPS2.Lib/Lang/Resources/SettingsResources.Designer.cs
generated
@ -11,46 +11,32 @@ namespace NAPS2.Lang.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SettingsResources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal SettingsResources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NAPS2.Lang.Resources.SettingsResources", typeof(SettingsResources).Assembly);
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("NAPS2.Lang.Resources.SettingsResources", typeof(SettingsResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@ -59,517 +45,304 @@ namespace NAPS2.Lang.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Black and White.
|
||||
/// </summary>
|
||||
internal static string BitDepth_1BlackAndWhite {
|
||||
get {
|
||||
return ResourceManager.GetString("BitDepth_1BlackAndWhite", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 24-bit Color.
|
||||
/// </summary>
|
||||
internal static string BitDepth_24Color {
|
||||
get {
|
||||
return ResourceManager.GetString("BitDepth_24Color", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Grayscale.
|
||||
/// </summary>
|
||||
internal static string BitDepth_8Grayscale {
|
||||
get {
|
||||
return ResourceManager.GetString("BitDepth_8Grayscale", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 100 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_100 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_100", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1200 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_1200 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_1200", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 150 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_150 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_150", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 200 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_200 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_200", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 300 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_300 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_300", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 400 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_400 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_400", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 600 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_600 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_600", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 800 dpi.
|
||||
/// </summary>
|
||||
internal static string Dpi_800 {
|
||||
get {
|
||||
return ResourceManager.GetString("Dpi_800", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} dpi.
|
||||
/// </summary>
|
||||
internal static string DpiFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("DpiFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No provider selected..
|
||||
/// </summary>
|
||||
internal static string EmailProvider_NotSelected {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProvider_NotSelected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom SMTP.
|
||||
/// </summary>
|
||||
internal static string EmailProviderType_CustomSmtp {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProviderType_CustomSmtp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Gmail.
|
||||
/// </summary>
|
||||
internal static string EmailProviderType_Gmail {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProviderType_Gmail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Outlook Web Access.
|
||||
/// </summary>
|
||||
internal static string EmailProviderType_OutlookWeb {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProviderType_OutlookWeb", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Center.
|
||||
/// </summary>
|
||||
internal static string EmailProviderType_Thunderbird {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProviderType_Thunderbird", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string EmailProvider_NotSelected {
|
||||
get {
|
||||
return ResourceManager.GetString("EmailProvider_NotSelected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string HorizontalAlign_Center {
|
||||
get {
|
||||
return ResourceManager.GetString("HorizontalAlign_Center", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Left.
|
||||
/// </summary>
|
||||
internal static string HorizontalAlign_Left {
|
||||
get {
|
||||
return ResourceManager.GetString("HorizontalAlign_Left", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Right.
|
||||
/// </summary>
|
||||
internal static string HorizontalAlign_Right {
|
||||
get {
|
||||
return ResourceManager.GetString("HorizontalAlign_Right", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Best.
|
||||
/// </summary>
|
||||
internal static string OcrMode_Best {
|
||||
get {
|
||||
return ResourceManager.GetString("OcrMode_Best", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Fast.
|
||||
/// </summary>
|
||||
internal static string OcrMode_Fast {
|
||||
get {
|
||||
return ResourceManager.GetString("OcrMode_Fast", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A3 (297x420 mm).
|
||||
/// </summary>
|
||||
internal static string PageSize_A3 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A3", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A4 (210x297 mm).
|
||||
/// </summary>
|
||||
internal static string PageSize_A4 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A5 (148x210 mm).
|
||||
/// </summary>
|
||||
internal static string PageSize_A5 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to B4 (250x353 mm).
|
||||
/// </summary>
|
||||
internal static string PageSize_B4 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_B4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to B5 (176x250 mm).
|
||||
/// </summary>
|
||||
internal static string PageSize_B5 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_B5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom....
|
||||
/// </summary>
|
||||
internal static string PageSize_Custom {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Custom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to US Legal (8.5x14 in).
|
||||
/// </summary>
|
||||
internal static string PageSize_Legal {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Legal", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to US Letter (8.5x11 in).
|
||||
/// </summary>
|
||||
internal static string PageSize_Letter {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Letter", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to cm.
|
||||
/// </summary>
|
||||
internal static string PageSizeUnit_Centimetre {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSizeUnit_Centimetre", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to in.
|
||||
/// </summary>
|
||||
internal static string PageSizeUnit_Inch {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSizeUnit_Inch", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to mm.
|
||||
/// </summary>
|
||||
internal static string PageSizeUnit_Millimetre {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSizeUnit_Millimetre", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default.
|
||||
/// </summary>
|
||||
internal static string PageSize_A3 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A3", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_A4 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_A5 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_A5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_B4 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_B4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_B5 {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_B5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_Custom {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Custom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_Legal {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Legal", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PageSize_Letter {
|
||||
get {
|
||||
return ResourceManager.GetString("PageSize_Letter", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PdfCompat_Default {
|
||||
get {
|
||||
return ResourceManager.GetString("PdfCompat_Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PDF/A-1b.
|
||||
/// </summary>
|
||||
internal static string PdfCompat_PdfA1B {
|
||||
get {
|
||||
return ResourceManager.GetString("PdfCompat_PdfA1B", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PDF/A-2b.
|
||||
/// </summary>
|
||||
internal static string PdfCompat_PdfA2B {
|
||||
get {
|
||||
return ResourceManager.GetString("PdfCompat_PdfA2B", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PDF/A-3b.
|
||||
/// </summary>
|
||||
internal static string PdfCompat_PdfA3B {
|
||||
get {
|
||||
return ResourceManager.GetString("PdfCompat_PdfA3B", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PDF/A-3u.
|
||||
/// </summary>
|
||||
internal static string PdfCompat_PdfA3U {
|
||||
get {
|
||||
return ResourceManager.GetString("PdfCompat_PdfA3U", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1:1.
|
||||
/// </summary>
|
||||
internal static string Scale_1_1 {
|
||||
get {
|
||||
return ResourceManager.GetString("Scale_1_1", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1:2.
|
||||
/// </summary>
|
||||
internal static string Scale_1_2 {
|
||||
get {
|
||||
return ResourceManager.GetString("Scale_1_2", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1:4.
|
||||
/// </summary>
|
||||
internal static string Scale_1_4 {
|
||||
get {
|
||||
return ResourceManager.GetString("Scale_1_4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1:8.
|
||||
/// </summary>
|
||||
internal static string Scale_1_8 {
|
||||
get {
|
||||
return ResourceManager.GetString("Scale_1_8", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Duplex.
|
||||
/// </summary>
|
||||
internal static string Source_Duplex {
|
||||
get {
|
||||
return ResourceManager.GetString("Source_Duplex", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Feeder.
|
||||
/// </summary>
|
||||
internal static string Source_Feeder {
|
||||
get {
|
||||
return ResourceManager.GetString("Source_Feeder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Glass.
|
||||
/// </summary>
|
||||
internal static string Source_Glass {
|
||||
get {
|
||||
return ResourceManager.GetString("Source_Glass", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Auto.
|
||||
/// </summary>
|
||||
internal static string TiffComp_Auto {
|
||||
get {
|
||||
return ResourceManager.GetString("TiffComp_Auto", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to CCITT4.
|
||||
/// </summary>
|
||||
internal static string TiffComp_Ccitt4 {
|
||||
get {
|
||||
return ResourceManager.GetString("TiffComp_Ccitt4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to LZW.
|
||||
/// </summary>
|
||||
internal static string TiffComp_Lzw {
|
||||
get {
|
||||
return ResourceManager.GetString("TiffComp_Lzw", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to None.
|
||||
/// </summary>
|
||||
internal static string TiffComp_None {
|
||||
get {
|
||||
return ResourceManager.GetString("TiffComp_None", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default.
|
||||
/// </summary>
|
||||
internal static string TwainImpl_Default {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Legacy (native UI only).
|
||||
/// </summary>
|
||||
internal static string TwainImpl_Legacy {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_Legacy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Memory Transfer.
|
||||
/// </summary>
|
||||
internal static string TwainImpl_MemXfer {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_MemXfer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Native Transfer.
|
||||
/// </summary>
|
||||
internal static string TwainImpl_NativeXfer {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_NativeXfer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Old DSM.
|
||||
/// </summary>
|
||||
internal static string TwainImpl_MemXfer {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_MemXfer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string TwainImpl_OldDsm {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_OldDsm", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to x64.
|
||||
/// </summary>
|
||||
internal static string TwainImpl_X64 {
|
||||
get {
|
||||
return ResourceManager.GetString("TwainImpl_X64", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default.
|
||||
/// </summary>
|
||||
internal static string WiaVersion_Default {
|
||||
get {
|
||||
return ResourceManager.GetString("WiaVersion_Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1.0.
|
||||
/// </summary>
|
||||
internal static string WiaVersion_Wia10 {
|
||||
get {
|
||||
return ResourceManager.GetString("WiaVersion_Wia10", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 2.0.
|
||||
/// </summary>
|
||||
internal static string WiaVersion_Wia20 {
|
||||
get {
|
||||
return ResourceManager.GetString("WiaVersion_Wia20", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string OcrMode_Fast {
|
||||
get {
|
||||
return ResourceManager.GetString("OcrMode_Fast", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string OcrMode_Best {
|
||||
get {
|
||||
return ResourceManager.GetString("OcrMode_Best", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,9 @@
|
||||
<data name="EmailProviderType_OutlookWeb" xml:space="preserve">
|
||||
<value>Outlook Web Access</value>
|
||||
</data>
|
||||
<data name="EmailProviderType_Thunderbird" xml:space="preserve">
|
||||
<value>Thunderbird</value>
|
||||
</data>
|
||||
<data name="EmailProvider_NotSelected" xml:space="preserve">
|
||||
<value>No provider selected.</value>
|
||||
</data>
|
||||
|
@ -3,4 +3,31 @@ namespace NAPS2.Util;
|
||||
public static class ProcessHelper
|
||||
{
|
||||
public static void OpenUrl(string url) => Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||
|
||||
public static bool IsSuccessful(string command, string args, int timeoutMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = Process.Start(new ProcessStartInfo(command, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
});
|
||||
if (process != null)
|
||||
{
|
||||
process.WaitForExit(timeoutMs);
|
||||
bool result = process.HasExited && process.ExitCode == 0;
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user