case 4173

This commit is contained in:
2023-05-09 22:23:54 +00:00
parent 079a6a6999
commit 82fa744de5
8 changed files with 93 additions and 18 deletions

2
.vscode/launch.json vendored
View File

@@ -119,7 +119,7 @@
"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;CommandTimeout=300;",
"AYANOVA_DATA_PATH": "c:\\temp\\ravendata",
"AYANOVA_USE_URLS": "http://*:7575;",
"AYANOVA_PERMANENTLY_ERASE_DATABASE":"true",
//"AYANOVA_PERMANENTLY_ERASE_DATABASE":"true",
//"AYANOVA_REMOVE_LICENSE_FROM_DB":"true",
//"AYANOVA_SET_SUPERUSER_PW": "abraxis",
"AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_14\\bin"

View File

@@ -2,7 +2,7 @@
![send email extension](img/ay-ex-direct-smtp.png)
The Send email extension can be used to send an email to the selected objects email address.
The Send email extension can be used to send an email to the selected (Active) object's email address.
## Authorization Roles required
@@ -18,6 +18,6 @@ The Send email extension is accessed from the [extensions](ay-extensions.md) men
## How the Send email extension works
Compose a message and start the job. AyaNova will attempt to send the message to the email address set for all selected objects with a small delay between each to avoid overloading your email server. Objects without an email address will be ignored.
Compose a message and start the job. AyaNova will attempt to send the message to the email address set for all selected objects with a small delay between each to avoid overloading your email server. Objects that are not set to Active or objects without an email address will be ignored.
**WARNING**: This extension allows you to mass email multiple objects at a time. AyaNova will automatically add a small delay between sending each message to prevent potentially overwhelming the email server, however, there may be limits on how many emails can be sent within a given time period so be sure to check with your email service provider to avoid potentially violating anti-spam policies.

View File

@@ -281,6 +281,18 @@ namespace AyaNova.Api.Controllers
if (batchDirectSMTPParams.SelectedRequest == null)
return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "batchDirectSMTPParams.DataListSelectedRequest is required"));
switch (batchDirectSMTPParams.SelectedRequest.AType)
{
case AyaType.Customer:
case AyaType.HeadOffice:
case AyaType.Vendor:
case AyaType.User:
break;
default:
return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "AType", "Specified Type not supported"));
}
if (!Authorized.HasModifyRole(HttpContext.Items, batchDirectSMTPParams.SelectedRequest.AType))
return StatusCode(403, new ApiNotAuthorizedResponse());
@@ -295,10 +307,12 @@ namespace AyaNova.Api.Controllers
UserIdFromContext.Id(HttpContext.Items),
UserTranslationIdFromContext.Id(HttpContext.Items));
var JobName = $"LT:BatchDirectSMTP - LT:{batchDirectSMTPParams.SelectedRequest.AType} ({batchDirectSMTPParams.SelectedRequest.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}";
var JobName = $"LT:BatchDirectSMTP - LT:{batchDirectSMTPParams.SelectedRequest.AType} ({batchDirectSMTPParams.SelectedRequest.SelectedRowIds.LongLength}), LT:User {UserNameFromContext.Name(HttpContext.Items)}, LT:MemoSubject '{batchDirectSMTPParams.Subject}'";
JObject o = JObject.FromObject(new
{
idList = batchDirectSMTPParams.SelectedRequest.SelectedRowIds
idList = batchDirectSMTPParams.SelectedRequest.SelectedRowIds,
subject = batchDirectSMTPParams.Subject,
message = batchDirectSMTPParams.TextBody
});
OpsJob j = new OpsJob();

View File

@@ -647,9 +647,6 @@ namespace AyaNova.Biz
SaveIt = false;
ClearErrors();
Customer o = null;
//save a fetch if it's a delete
if (job.SubType != JobSubType.Delete)
o = await GetAsync(id, false);
switch (job.SubType)
{
case JobSubType.TagAddAny:
@@ -658,6 +655,7 @@ namespace AyaNova.Biz
case JobSubType.TagRemove:
case JobSubType.TagReplaceAny:
case JobSubType.TagReplace:
o = await GetAsync(id, false);
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
break;
case JobSubType.Delete:
@@ -667,6 +665,23 @@ namespace AyaNova.Biz
FailedObjectCount++;
}
break;
case JobSubType.DirectSMTP:
o = await GetAsync(id, false);
if (o != null && o.Active && !string.IsNullOrWhiteSpace(o.EmailAddress))
{
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(o.EmailAddress, (string)jobData["subject"], (string)jobData["message"], ServerGlobalOpsSettingsCache.Notify, null, null, null);
await Task.Delay(AyaNova.Util.ServerBootConfig.JOB_OBJECT_EMAIL_LOOP_DELAY);//a small delay to not overwhelm the mail server
}
catch (Exception ex)
{
FailedObjectCount++;
await NotifyEventHelper.AddOpsProblemEvent("SMTP direct message failed", ex);
}
}
break;
default:
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
}

View File

@@ -525,9 +525,6 @@ namespace AyaNova.Biz
SaveIt = false;
ClearErrors();
HeadOffice o = null;
//save a fetch if it's a delete
if (job.SubType != JobSubType.Delete)
o = await GetAsync(id, false);
switch (job.SubType)
{
case JobSubType.TagAddAny:
@@ -536,6 +533,7 @@ namespace AyaNova.Biz
case JobSubType.TagRemove:
case JobSubType.TagReplaceAny:
case JobSubType.TagReplace:
o = await GetAsync(id, false);
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
break;
case JobSubType.Delete:
@@ -545,6 +543,23 @@ namespace AyaNova.Biz
FailedObjectCount++;
}
break;
case JobSubType.DirectSMTP:
o = await GetAsync(id, false);
if (o != null && o.Active && !string.IsNullOrWhiteSpace(o.EmailAddress))
{
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(o.EmailAddress, (string)jobData["subject"], (string)jobData["message"], ServerGlobalOpsSettingsCache.Notify, null, null, null);
await Task.Delay(AyaNova.Util.ServerBootConfig.JOB_OBJECT_EMAIL_LOOP_DELAY);//a small delay to not overwhelm the mail server
}
catch (Exception ex)
{
FailedObjectCount++;
await NotifyEventHelper.AddOpsProblemEvent("SMTP direct message failed", ex);
}
}
break;
default:
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
}

View File

@@ -1262,9 +1262,6 @@ namespace AyaNova.Biz
//a little different than normal here because the built in getasync doesn't return
//a full User object normally
User o = null;
//save a fetch if it's a delete
if (job.SubType != JobSubType.Delete)
o = await GetAsync(id, false);
switch (job.SubType)
{
case JobSubType.TagAddAny:
@@ -1273,6 +1270,7 @@ namespace AyaNova.Biz
case JobSubType.TagRemove:
case JobSubType.TagReplaceAny:
case JobSubType.TagReplace:
o = await GetAsync(id, false);
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
break;
case JobSubType.Delete:
@@ -1282,6 +1280,23 @@ namespace AyaNova.Biz
FailedObjectCount++;
}
break;
case JobSubType.DirectSMTP:
o = await ct.User.AsNoTracking().Include(o => o.UserOptions).FirstOrDefaultAsync(z => z.Id == id);
if (o != null && o.Active && !string.IsNullOrWhiteSpace(o.UserOptions.EmailAddress))
{
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(o.UserOptions.EmailAddress, (string)jobData["subject"], (string)jobData["message"], ServerGlobalOpsSettingsCache.Notify, null, null, null);
await Task.Delay(AyaNova.Util.ServerBootConfig.JOB_OBJECT_EMAIL_LOOP_DELAY);//a small delay to not overwhelm the mail server
}
catch (Exception ex)
{
FailedObjectCount++;
await NotifyEventHelper.AddOpsProblemEvent("SMTP direct message failed", ex);
}
}
break;
default:
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
}

View File

@@ -457,9 +457,6 @@ namespace AyaNova.Biz
SaveIt = false;
ClearErrors();
Vendor o = null;
//save a fetch if it's a delete
if (job.SubType != JobSubType.Delete)
o = await GetAsync(id, false);
switch (job.SubType)
{
case JobSubType.TagAddAny:
@@ -468,6 +465,7 @@ namespace AyaNova.Biz
case JobSubType.TagRemove:
case JobSubType.TagReplaceAny:
case JobSubType.TagReplace:
o = await GetAsync(id, false);
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
break;
case JobSubType.Delete:
@@ -477,6 +475,23 @@ namespace AyaNova.Biz
FailedObjectCount++;
}
break;
case JobSubType.DirectSMTP:
o = await GetAsync(id, false);
if (o != null && o.Active && !string.IsNullOrWhiteSpace(o.EmailAddress))
{
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(o.EmailAddress, (string)jobData["subject"], (string)jobData["message"], ServerGlobalOpsSettingsCache.Notify, null, null, null);
await Task.Delay(AyaNova.Util.ServerBootConfig.JOB_OBJECT_EMAIL_LOOP_DELAY);//a small delay to not overwhelm the mail server
}
catch (Exception ex)
{
FailedObjectCount++;
await NotifyEventHelper.AddOpsProblemEvent("SMTP direct message failed", ex);
}
}
break;
default:
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
}

View File

@@ -17,6 +17,7 @@ namespace AyaNova.Util
internal const int FAILED_AUTH_DELAY = 3000;//ms
internal const int JOB_OBJECT_HANDLE_BATCH_JOB_LOOP_DELAY = 200;//ms this delay is a temporary measure to ensure super big time consuming batch jobs don't use all server CPU resources
internal const int JOB_PROGRESS_UPDATE_AND_CANCEL_CHECK_SECONDS = 5;//seconds between progress updates and checks for cancellation of long running jobs
internal const int JOB_OBJECT_EMAIL_LOOP_DELAY = 500;//ms this delay ensures multiple email sendings in a job don't overwhelm the mail server
//UPLOAD LIMITS 1048576 = 1MiB for testing 10737420000 10737418240 10,737,418,240
internal const long MAX_ATTACHMENT_UPLOAD_BYTES = 10737420000;//slight bit of overage as 10737418241=10GiB