hi, yes sure, basically sends an email and then inserts a domain entity and marks as processed, or sending email error if there's an error.
public class CertificateEmailSendingJob : AsyncBackgroundJob<CertificateEmailSendingArgs>, ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ISettingProvider _settingsProvider;
private readonly ICurrentTenant _currentTenant;
private readonly IDonationCertificateRepository _certificateRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
public CertificateEmailSendingJob(IEmailSender emailSender,
ISettingProvider settingsProvider,
ICurrentTenant currentTenant,
IDonationCertificateRepository certificateRepository,
IUnitOfWorkManager unitOfWorkManager,
ICurrentPrincipalAccessor currentPrincipalAccessor)
{
_emailSender = emailSender;
_settingsProvider = settingsProvider;
_currentTenant = currentTenant;
_certificateRepository = certificateRepository;
_unitOfWorkManager = unitOfWorkManager;
_currentPrincipalAccessor = currentPrincipalAccessor;
}
public override async Task ExecuteAsync(CertificateEmailSendingArgs args)
{
var claims = JobsExtensions.GetUserAsync(args.User.Id, args.User.Name, args.User.Surname, args.User.UserName, args.User.Roles);
using (_currentPrincipalAccessor.Change(claims.claims))
{
using (_currentTenant.Change(args.TenantId))
{
var from = await _settingsProvider.GetOrNullAsync(FundraisingSettingsConst.SmtpUserName);
using var memoryStream = new MemoryStream(args.CertificateFile);
var attachment = new Attachment(memoryStream, new ContentType(MediaTypeNames.Application.Pdf))
{
ContentDisposition = { FileName = args.CertificateFileName }
};
var message = new MailMessage(
from,
args.DonorEmail,
args.EmailSubject,
args.EmailBody);
message.Attachments.Add(attachment);
using var uow = _unitOfWorkManager.Begin(
requiresNew: true, isTransactional: false);
try
{
await _emailSender.SendAsync(message);
var certificateRecord =
new DonationCertificate(Guid.NewGuid(), args.DonorId, args.LabelId,
args.EmailTemplateLabelId,
DonationCertificateStatus.Processed,
args.Year,
args.DonationId);
await _certificateRepository.InsertAsync(certificateRecord);
}
catch (Exception)
{
var certificateRecord =
new DonationCertificate(Guid.NewGuid(), args.DonorId, args.LabelId,
args.EmailTemplateLabelId,
DonationCertificateStatus.EmailSendingError,
args.Year,
args.DonationId);
await _certificateRepository.InsertAsync(certificateRecord);
}
await uow.CompleteAsync();
}
}
}
}
public static class JobsExtensions
{
public static (Guid? userId, ClaimsPrincipal claims) GetUserAsync(Guid? userId, string name, string surname, string userName, string[] roleNames)
{
var claimsList = new List<Claim>
{
new(AbpClaimTypes.UserId, userId.ToString()),
new(AbpClaimTypes.Name, name ?? "BackgroundJobUser"),
new(AbpClaimTypes.SurName, surname ?? "BackgroundJobUser"),
new(AbpClaimTypes.UserName, userName)
};
claimsList.AddRange(roleNames
.Select(_ => new Claim(AbpClaimTypes.Role, _)).ToList());
return (userId, new ClaimsPrincipal(new ClaimsIdentity(claimsList)));
}
}
public class CertificateEmailSendingArgs
{
public Guid? TenantId { get; set; }
public string DonorEmail { get; set; }
public string EmailSubject { get; set; }
public string EmailBody { get; set; }
public string CertificateFileName { get; set; }
public byte[] CertificateFile { get; set; }
public Guid DonorId { get; set; }
public Guid LabelId { get; set; }
public Guid EmailTemplateLabelId { get; set; }
public int? Year { get; set; }
public Guid? DonationId { get; set; }
public UserArgs User { get; set; }
}
internal class DonationCertificateRepository: EfCoreRepository<FundraisingDbContext, DonationCertificate, Guid>,IDonationCertificateRepository
I tried to switch order of change tenant and change user, same result, CreatorId is null. Something i should be doing wrong changing user, because values when i generate ClaimsPrincipal are correct.
Hi,
I'm switching tenant, with ICurrentTenant, _currentTenant.Change(args.TenantId) and TenantId is correctly stored. But switching user with ICurrentPrincipalAccessor _currentPrincipalAccessor.Change(claims) where claims are generated like this:
public static (Guid? userId, ClaimsPrincipal claims) GetUserAsync(Guid? userId, string name, string surname, string userName, string[] roleNames)
{
var claimsList = new List<Claim>
{
new(AbpClaimTypes.UserId, userId.ToString()),
new(AbpClaimTypes.Name, name ?? "BackgroundJobUser"),
new(AbpClaimTypes.SurName, surname ?? "BackgroundJobUser"),
new(AbpClaimTypes.UserName, userName)
};
claimsList.AddRange(roleNames
.Select(_ => new Claim(AbpClaimTypes.Role, _)).ToList());
return (userId, new ClaimsPrincipal(new ClaimsIdentity(claimsList)));
}
But CreatorId still null, what am I doing wrong?
Hi,
In wich class is implemented that logic in Abp framework? I only see AddVirtualJson to AbpLocalizationOptions Resources
Thanks