### C# - Lazy GraphServiceClient Initialization with Azure AD Credentials Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Demonstrates the lazy initialization of an authenticated Microsoft Graph client using Azure AD client credentials. It shows how to configure tenant ID, client ID, client secret, and scopes. The client is automatically created upon first access and cached for subsequent use. This example also includes a manual client creation for comparison and highlights how the client is used for sending emails. ```csharp using Azure.Identity; using Microsoft.Graph; using Progress.Sitefinity.Office365.Mail.Sender.Configuration; public class GraphClientExample { public void AccessGraphClient() { // Configure profile var profile = new Office365SenderProfileElement(null) { TenantId = "12345678-1234-1234-1234-123456789abc", ClientId = "87654321-4321-4321-4321-abcdef123456", ClientSecret = "your-client-secret", Scopes = "https://graph.microsoft.com/.default,Mail.Send" // Multiple scopes supported }; var mailSender = new Office365MailSender(profile); // GraphClient is lazy-loaded - created on first access // This property getter calls CreateGraphClient internally GraphServiceClient graphClient = mailSender.GraphClient; // Client is now authenticated and ready to use // Scopes are parsed from comma-separated string // ClientSecretCredential is created with TenantId, ClientId, ClientSecret // The client is reused for subsequent calls (cached in mailSender.graphClient field) GraphServiceClient sameClient = mailSender.GraphClient; // Returns cached instance // Equivalent manual creation: string[] scopes = profile.Scopes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var credential = new ClientSecretCredential( profile.TenantId, profile.ClientId, profile.ClientSecret ); var manualClient = new GraphServiceClient(credential, scopes); // Use for sending mail (done automatically by SendMessage) // graphClient.Users["sender@company.com"].SendMail.PostAsync(requestBody); } } // Error handling example public void GraphClientWithErrorHandling() { try { var profile = new Office365SenderProfileElement(null) { TenantId = "invalid-tenant-id", ClientId = "invalid-client-id", ClientSecret = "invalid-secret", Scopes = "https://graph.microsoft.com/.default" }; var sender = new Office365MailSender(profile); var client = sender.GraphClient; // May throw during authentication } catch (Exception ex) { // Exception is automatically logged to Sitefinity error log via Log.Write Console.WriteLine($"Failed to create Graph client: {ex.Message}"); throw; // Re-thrown for higher-level handling } } ``` -------------------------------- ### C#: Register Office365 Notification Profile Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# code snippet demonstrates how to manually register the Office365 notification profile during Sitefinity's application startup. It subscribes to the `Bootstrapper.Initialized` event to perform registration after Sitefinity has bootstrapped, ensuring the profile is configured with default settings or checks for its existing presence. This manual example is for educational purposes, as automatic registration is typically handled via `AssemblyInfo.cs`. ```csharp using System; using Progress.Sitefinity.Office365.Mail.Sender; using Progress.Sitefinity.Office365.Mail.Sender.Configuration; using Progress.Sitefinity.Office365.MailSender.Notifications; using Telerik.Sitefinity.Abstractions; using Telerik.Sitefinity.Configuration; using Telerik.Sitefinity.Services.Notifications.Configuration; using Telerik.Sitefinity.Web.Configuration; // This is called automatically via [PreApplicationStartMethod] attribute in AssemblyInfo.cs // No manual invocation needed - shown here for educational purposes public class Example { public void ManualRegistrationExample() { // Subscribe to bootstrapper initialized event Bootstrapper.Initialized += (sender, e) => { // Only execute after Sitefinity has fully bootstrapped if (e.CommandName == "Bootstrapped") { // Register localization resources Res.RegisterResource(); // Use elevated permissions to modify configuration using (new ElevatedConfigModeRegion()) { var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); // Check if Office365 profile already exists SenderProfileElement existingProfile; if (!notificationConfig.Profiles.TryGetValue("Office365", out existingProfile)) { // Create new profile with defaults var newProfile = new Office365SenderProfileElement(notificationConfig.Profiles) { ProfileName = "Office365", SenderType = typeof(Office365MailSender).FullName, BatchSize = 100, BatchPauseInterval = 0 }; notificationConfig.Profiles.Add(newProfile); configManager.SaveSection(notificationConfig); Console.WriteLine("Office365 notification profile registered successfully"); } else { Console.WriteLine("Office365 notification profile already exists"); } } } }; } } // The actual automatic registration happens via AssemblyInfo.cs: // [assembly: PreApplicationStartMethod(typeof(Startup), "OnPreApplicationStart")] // This ensures the profile is available immediately after Sitefinity starts ``` -------------------------------- ### Create and Configure MessageInfo for Sitefinity Emails Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Demonstrates how to create an IMessageTemplateRequest and then use it to instantiate a MessageInfo object. This includes setting template content, overriding sender details, adding custom headers, and including additional metadata for email processing within Sitefinity. ```csharp using Progress.Sitefinity.Office365.Mail.Sender.Model; using Telerik.Sitefinity.Services.Notifications.Composition; using System.Collections.Generic; // Create template IMessageTemplateRequest template = new MessageTemplateRequest { Subject = "Account Verification Required", BodyHtml = "

Verify Your Account

Click the link to verify: {VerificationLink}

", PlainTextVersion = "Verify Your Account - Click the link to verify: {VerificationLink}", TemplateSenderEmailAddress = "noreply@company.com", TemplateSenderName = "Company Verification System", SystemMessage = "Account verification is required to continue", SystemUrl = "https://company.com/verify" }; // Create MessageInfo with override sender var message = new MessageInfo( template, "security@company.com", // Override sender email "Security Team" // Override sender name ); // Properties are accessible and modifiable Console.WriteLine($"Subject: {message.Subject}"); // "Account Verification Required" Console.WriteLine($"Is HTML: {message.IsHtml}"); // true Console.WriteLine($"Sender: {message.SenderName} <{message.SenderEmailAddress}>"); // "Security Team " Console.WriteLine($"Template Sender: {message.TemplateSenderEmailAddress}"); // "noreply@company.com" Console.WriteLine($"Body HTML: {message.BodyHtml}"); Console.WriteLine($"Plain Text: {message.PlainTextVersion}"); Console.WriteLine($"System Message: {message.SystemMessage}"); Console.WriteLine($"System URL: {message.SystemUrl}"); // Custom headers (empty by default) message.CustomMessageHeaders.Add("X-Priority", "High"); message.CustomMessageHeaders.Add("X-Campaign-ID", "verify-2024"); // Additional metadata message.ResolveKey = "account-verification"; message.ModuleName = "SecurityModule"; message.LastModified = System.DateTime.UtcNow; message.AdditionalMessageData = "{\"userId\":12345,\"attempt\":1}"; // Get localized title string title = message.GetTitle(); // Returns Subject string localizedTitle = message.GetTitle(new System.Globalization.CultureInfo("fr-FR")); // Use in sender // var sender = new Office365MailSender(profile); // var result = sender.SendMessage(message, subscriber); ``` -------------------------------- ### Send Batch Emails with Office365MailSender in C# Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Demonstrates configuring and using the Office365MailSender to send emails in batches to multiple subscribers. It includes settings for batch size, pause intervals, sender resolution, and individual subscriber error tracking. Dependencies include Sitefinity and Office 365 mail sender components. ```csharp using System.Collections.Generic; using Progress.Sitefinity.Office365.MailSender.Notifications; using Telerik.Sitefinity.Services.Notifications; using Telerik.Sitefinity.Services.Notifications.Composition; // Configure profile with batch settings var profile = new Office365SenderProfileElement(null) { TenantId = "12345678-1234-1234-1234-123456789abc", ClientId = "87654321-4321-4321-4321-abcdef123456", ClientSecret = "your-client-secret-value", Scopes = "https://graph.microsoft.com/.default", DefaultSenderEmailAddress = "noreply@company.com", DefaultSenderName = "Company System", BatchSize = 50, // Process 50 emails per batch BatchPauseInterval = 2 // Wait 2 seconds between batches }; var mailSender = new Office365MailSender(profile); // Create message job with template IMessageJobRequest messageJob = new MessageJobRequest { SenderEmailAddress = "marketing@company.com", // Overrides template and default SenderName = "Marketing Team", // Overrides template and default MessageTemplate = new MessageTemplateRequest { Subject = "Monthly Newsletter - {Month}", BodyHtml = "

Newsletter

Dear {Name}, here is your monthly update...

", PlainTextVersion = "Newsletter - Dear {Name}, here is your monthly update...", TemplateSenderEmailAddress = "newsletter@company.com", // Fallback if job sender not set TemplateSenderName = "Newsletter System" // Fallback if job sender not set } }; // Create subscriber list var subscribers = new List { new SubscriberResponse { Email = "user1@example.com", SubscriberData = new { Name = "John", Month = "January" } }, new SubscriberResponse { Email = "user2@example.com", SubscriberData = new { Name = "Jane", Month = "January" } }, new SubscriberResponse { Email = "user3@example.com", SubscriberData = new { Name = "Bob", Month = "January" } } }; // Send batch SendResult batchResult = mailSender.SendMessage(messageJob, subscribers); // Check batch properties Console.WriteLine($"Batch size: {mailSender.BatchSize}"); // Output: 50 Console.WriteLine($"Pause interval: {mailSender.PauseInterval}s"); // Output: 2s // Examine individual results foreach (var subscriber in subscribers) { var notifiable = subscriber as INotifiable; if (notifiable != null) { Console.WriteLine($"{subscriber.Email}: {notifiable.Result} (Notified: {notifiable.IsNotified})"); } } // Overall batch result if (batchResult.Type == SendResultType.Success) { Console.WriteLine("All emails sent successfully"); } else if (batchResult.Type == SendResultType.Failed) { Console.WriteLine("Batch encountered failures"); } ``` -------------------------------- ### Send Welcome Email using Office 365 Mail Sender Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# function sends a personalized welcome email to a single recipient using the Office365MailSender. It constructs a message template, creates a subscriber object, and then sends the email. The function returns true on success and false on failure, with error details logged to the console. It handles potential OData errors from Microsoft Graph API and general exceptions. ```csharp public bool SendWelcomeEmail(string recipientEmail, string recipientName) { Office365MailSender sender = null; try { // Get configuration for Office 365 sender var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); var profileElement = notificationConfig.Profiles["Office365"] as Office365SenderProfileElement; sender = new Office365MailSender(profileElement); // Create message template var template = new MessageTemplateRequest { Subject = "Welcome to Our Platform!", BodyHtml = @"

This is an automated message. Please do not reply.

", PlainTextVersion = $"Welcome {recipientName}!\n\nThank you for joining our platform. We're excited to have you on board.\n\nTo get started:\n- Complete your profile\n- Explore our features\n- Connect with other users\n\nIf you have any questions, feel free to contact our support team.\n\nThis is an automated message. Please do not reply.", TemplateSenderEmailAddress = "welcome@company.com", TemplateSenderName = "Welcome Team" }; // Create message var message = new MessageInfo(template, "welcome@company.com", "Welcome Team"); // Create subscriber var subscriber = new SubscriberRequest { Email = recipientEmail }; // Send message SendResult result = sender.SendMessage(message, subscriber); if (result.Type == SendResultType.Success) { Console.WriteLine($"Welcome email sent successfully to {recipientEmail}"); return true; } else { Console.WriteLine($"Failed to send email: {result.Type}"); return false; } } catch (ODataError odataError) { Console.WriteLine($"Microsoft Graph API Error: {odataError.Error.Message}"); Console.WriteLine($"Error Code: {odataError.Error.Code}"); return false; } catch (Exception ex) { Console.WriteLine($"Error sending welcome email: {ex.Message}"); return false; } finally { sender?.Dispose(); } } ``` -------------------------------- ### Configure Office365 Sender Profile in C# Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# code demonstrates how to create and configure an `Office365SenderProfileElement` for sending emails via Office365. It covers setting Azure AD credentials, Graph API scopes, default sender information, and batch processing settings. The code also shows how to initialize the profile from a dictionary and export it back to a dictionary, with secrets automatically encrypted. ```csharp using System.Collections.Generic; using Progress.Sitefinity.Office365.Mail.Sender.Configuration; using Telerik.Sitefinity.Configuration; using Telerik.Sitefinity.Services.Notifications.Configuration; using Telerik.Sitefinity.Web.Configuration; // Get Sitefinity configuration manager var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); // Create new Office365 profile var office365Profile = new Office365SenderProfileElement(notificationConfig.Profiles) { // Profile identification ProfileName = "Office365Production", SenderType = "Progress.Sitefinity.Office365.MailSender.Notifications.Office365MailSender", // Azure AD OAuth configuration TenantId = "your-tenant-id-guid", ClientId = "your-app-client-id-guid", ClientSecret = "your-client-secret-value", // Automatically encrypted with [SecretData] Scopes = "https://graph.microsoft.com/.default", // Or comma-separated: "Mail.Send,User.Read" // Default sender information DefaultSenderEmailAddress = "system@company.com", DefaultSenderName = "Company System", // Batch processing settings BatchSize = 100, BatchPauseInterval = 0 // No pause between batches }; // Add to configuration notificationConfig.Profiles.Add(office365Profile); configManager.SaveSection(notificationConfig); // Initialize from dictionary (useful for API/UI scenarios) var configDict = new Dictionary { { "tenantId", "12345678-1234-1234-1234-123456789abc" }, { "clientId", "87654321-4321-4321-4321-abcdef123456" }, { "clientSecret", "secret-value-here" }, { "scopes", "https://graph.microsoft.com/.default, Mail.Send" }, // Whitespace removed automatically { "defaultSenderEmailAddress", "noreply@company.com" }, { "defaultSenderName", "No Reply" } }; office365Profile.Initialize(configDict); // Export to dictionary Dictionary exportedConfig = office365Profile.ToDictionary(); Console.WriteLine($"TenantId: {exportedConfig["tenantId"]}"); Console.WriteLine($"ClientSecret: {exportedConfig["clientSecret"]}"); // Encrypted value ``` -------------------------------- ### Use Office365 Sender Profile Proxy Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# code illustrates using `Office365SenderProfileProxy` to access and manipulate Office365 mail sender configurations. It shows how to create a proxy from an existing profile, access its properties, create a new proxy for API submission, and utilize predefined configuration keys for accessing settings. ```csharp using Progress.Sitefinity.Office365.Mail.Sender.Configuration; using Telerik.Sitefinity.Services.Notifications.Configuration; // Create proxy from existing profile ISenderProfile existingProfile = /* get from config */; var proxy = new Office365SenderProfileProxy(existingProfile); // Access Office365 configuration Console.WriteLine($"Tenant: {proxy.TenantId}"); Console.WriteLine($"Client: {proxy.ClientId}"); Console.WriteLine($"Scopes: {proxy.Scopes}"); Console.WriteLine($"Default Email: {proxy.DefaultSenderEmailAddress}"); Console.WriteLine($"Default Name: {proxy.DefaultSenderName}"); // Batch settings Console.WriteLine($"Batch Size: {proxy.BatchSize}"); Console.WriteLine($"Pause Interval: {proxy.BatchPauseInterval}s"); // Create new proxy for API submission var newProxy = new Office365SenderProfileProxy { // Azure/OAuth settings TenantId = "12345678-1234-1234-1234-123456789abc", ClientId = "87654321-4321-4321-4321-abcdef123456", ClientSecret = "your-client-secret", Scopes = "https://graph.microsoft.com/.default", // Sender settings DefaultSenderEmailAddress = "api@company.com", DefaultSenderName = "API System", SenderType = "Progress.Sitefinity.Office365.MailSender.Notifications.Office365MailSender", // Batch settings BatchSize = 75, BatchPauseInterval = 1, // Legacy SMTP properties (optional, for backward compatibility) Host = "", // Not used with Graph API Port = 0, // Not used with Graph API Username = "", // Not used with Graph API Password = "", // Not used with Graph API UseSSL = false // Not used with Graph API }; // Use configuration keys string tenantKey = Office365SenderProfileProxy.Office365Keys.TenantId; // "tenantId" string clientKey = Office365SenderProfileProxy.Office365Keys.ClientId; // "clientId" string secretKey = Office365SenderProfileProxy.Office365Keys.ClientSecret; // "clientSecret" string scopesKey = Office365SenderProfileProxy.Office365Keys.Scopes; // "scopes" string senderEmailKey = Office365SenderProfileProxy.Office365Keys.DefaultSenderEmailAddress; // "defaultSenderEmailAddress" string batchSizeKey = Office365SenderProfileProxy.Office365Keys.BatchSize; // "batchSize" // Access via CustomProperties dictionary string tenant = proxy.CustomProperties[Office365SenderProfileProxy.Office365Keys.TenantId]; ``` -------------------------------- ### Define Message Job Request Object Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Represents a request object for sending email jobs, containing sender information and a message template. Implements the IMessageJobRequest interface. ```csharp public class MessageJobRequest : IMessageJobRequest { public string SenderEmailAddress { get; set; } public string SenderName { get; set; } public IMessageTemplateRequest MessageTemplate { get; set; } } ``` -------------------------------- ### Define Message Template Request Object Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Represents a request object for email message templates, including subject, HTML body, plain text version, sender details, and system information. Implements the IMessageTemplateRequest interface. ```csharp public class MessageTemplateRequest : IMessageTemplateRequest { public string Subject { get; set; } public string BodyHtml { get; set; } public string PlainTextVersion { get; set; } public string TemplateSenderEmailAddress { get; set; } public string TemplateSenderName { get; set; } public string SystemMessage { get; set; } public string SystemUrl { get; set; } } ``` -------------------------------- ### Define Subscriber Request Object Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Represents a request object for subscriber data, containing only the email address. Implements the ISubscriberRequest interface. ```csharp public class SubscriberRequest : ISubscriberRequest { public string Email { get; set; } } ``` -------------------------------- ### Send Newsletter in Batch using Office 365 Mail Sender Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# function sends a newsletter to a list of recipients in batches using the Office365MailSender. It retrieves sender profile information from Sitefinity's configuration, constructs a newsletter message, converts recipients into subscriber objects, and then sends the batch. The function logs the sending process and provides feedback on batch size and pause intervals. It includes error handling for configuration retrieval and sending operations. ```csharp public SendResult SendNewsletterBatch(List recipients) { Office365MailSender sender = null; try { // Get profile var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); var profileElement = notificationConfig.Profiles["Office365"] as Office365SenderProfileElement; sender = new Office365MailSender(profileElement); // Create message job var messageJob = new MessageJobRequest { SenderEmailAddress = "newsletter@company.com", SenderName = "Company Newsletter", MessageTemplate = new MessageTemplateRequest { Subject = "Monthly Update - December 2024", BodyHtml = @"\n \n \n

December Newsletter

\n

Dear valued customer,

\n

Here are this month's highlights...

\n
    \n
  • New feature releases
  • \n
  • Upcoming events
  • \n
  • Special offers
  • \n
\n

Thank you for being part of our community!

\n \n ", PlainTextVersion = "December Newsletter - Dear valued customer, here are this month's highlights...", TemplateSenderEmailAddress = "newsletter@company.com", TemplateSenderName = "Newsletter System" } }; // Convert to subscriber responses var subscribers = new List(); foreach (var recipient in recipients) { subscribers.Add(new SubscriberResponse { Email = recipient.Email, SubscriberData = recipient }); } // Send batch Console.WriteLine($"Sending newsletter to {subscribers.Count} recipients..."); Console.WriteLine($"Batch size: {sender.BatchSize}, Pause interval: {sender.PauseInterval}s"); SendResult batchResult = sender.SendMessage(messageJob, subscribers); // Report results int successCount = 0; int failCount = 0; // ... (rest of the reporting logic) return batchResult; } catch (Exception ex) { Console.WriteLine($"Error sending newsletter batch: {ex.Message}"); return new SendResult { Type = SendResultType.Failure, ErrorMessage = ex.Message }; } finally { sender?.Dispose(); } } ``` -------------------------------- ### Configure Office365 Mail Sender Profile in Sitefinity (C#) Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Configures a new Office365 sender profile within Sitefinity's notification settings. This involves setting up Azure AD tenant, client ID, client secret, and email sender details. Prerequisites include an Azure AD app registration with necessary API permissions. ```csharp using System; using System.Collections.Generic; using Azure.Identity; using Microsoft.Graph; using Microsoft.Graph.Models.ODataErrors; using Progress.Sitefinity.Office365.Mail.Sender.Configuration; using Progress.Sitefinity.Office365.MailSender.Notifications; using Progress.Sitefinity.Office365.Mail.Sender.Model; using Telerik.Sitefinity.Configuration; using Telerik.Sitefinity.Services.Notifications; using Telerik.Sitefinity.Services.Notifications.Configuration; using Telerik.Sitefinity.Services.Notifications.Composition; namespace CompanyName.EmailIntegration { /// /// Complete Office365 mail integration example for Sitefinity CMS /// Prerequisites: /// 1. Azure AD tenant with app registration /// 2. App registration with client secret created /// 3. API permissions granted: Mail.Send (Application permission) /// 4. Admin consent granted for the application /// public class Office365EmailIntegration { // Step 1: Configure Office365 Profile in Sitefinity public void ConfigureOffice365Profile() { try { var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); // Check if profile exists SenderProfileElement existingProfile; if (notificationConfig.Profiles.TryGetValue("Office365", out existingProfile)) { Console.WriteLine("Office365 profile already exists"); return; } // Create new profile var profile = new Office365SenderProfileElement(notificationConfig.Profiles) { // Profile settings ProfileName = "Office365", SenderType = typeof(Office365MailSender).FullName, // Azure AD settings (from Azure Portal) TenantId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", ClientId = "11111111-2222-3333-4444-555555555555", ClientSecret = "your~client~secret~from~azure~portal", Scopes = "https://graph.microsoft.com/.default", // Email settings DefaultSenderEmailAddress = "noreply@company.com", DefaultSenderName = "Company Notifications", // Batch settings BatchSize = 100, BatchPauseInterval = 0 }; notificationConfig.Profiles.Add(profile); configManager.SaveSection(notificationConfig); Console.WriteLine("Office365 profile configured successfully"); } catch (Exception ex) { Console.WriteLine($"Configuration error: {ex.Message}"); throw; } } // Step 2: Send Welcome Email (Single Recipient) public bool SendWelcomeEmail(string recipientEmail, string recipientName) { Office365MailSender sender = null; try { // Get configuration var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); var profileElement = notificationConfig.Profiles["Office365"] as Office365SenderProfileElement; if (profileElement == null) { throw new InvalidOperationException("Office365 profile not found"); } // Create sender sender = new Office365MailSender(profileElement); // Create template var template = new MessageTemplateRequest { Subject = $("Welcome to Our Platform, {recipientName}!"), BodyHtml = $

Welcome {recipientName}!

Thank you for joining our platform. We're excited to have you on board.

To get started:

  • Complete your profile
  • Explore our features
  • Connect with other users

If you have any questions, feel free to contact our support team.

``` -------------------------------- ### Process Newsletter Batch with Microsoft 365 Mail Sender Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Iterates through subscribers to send newsletter batches, tracking success and failure counts. Logs detailed error messages for failed deliveries and provides a summary of the batch operation. Ensures proper disposal of the sender object. ```csharp foreach (var subscriber in subscribers) { var notifiable = subscriber as INotifiable; if (notifiable != null && notifiable.IsNotified) { successCount++; } else { failCount++; Console.WriteLine($"Failed to send to: {subscriber.Email}"); } } Console.WriteLine($"Newsletter batch complete: {successCount} sent, {failCount} failed"); return batchResult; } catch (Exception ex) { Console.WriteLine($"Batch processing error: {ex.Message}"); throw; } finally { sender?.Dispose(); } ``` -------------------------------- ### Define Subscriber Response Object Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Represents a response object for subscriber data, including email, additional data, send result type, and notification status. Implements both ISubscriberResponse and INotifiable interfaces. ```csharp public class SubscriberResponse : ISubscriberResponse, INotifiable { public string Email { get; set; } public object SubscriberData { get; set; } public SendResultType Result { get; set; } public bool IsNotified { get; set; } } ``` -------------------------------- ### Test Microsoft Graph API Connection Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Validates the connection to the Microsoft Graph API by attempting to instantiate the Office365MailSender and access its GraphClient. Logs connection details such as TenantId, ClientId, and Scopes. Handles potential exceptions during the connection test. ```csharp public bool TestGraphConnection() { try { var configManager = ConfigManager.GetManager(); var notificationConfig = configManager.GetSection(); var profileElement = notificationConfig.Profiles["Office365"] as Office365SenderProfileElement; var sender = new Office365MailSender(profileElement); // Access GraphClient to trigger authentication GraphServiceClient client = sender.GraphClient; Console.WriteLine("Successfully connected to Microsoft Graph API"); Console.WriteLine($"TenantId: {profileElement.TenantId}"); Console.WriteLine($"ClientId: {profileElement.ClientId}"); Console.WriteLine($"Scopes: {profileElement.Scopes}"); sender.Dispose(); return true; } catch (Exception ex) { Console.WriteLine($"Connection test failed: {ex.Message}"); return false; } } ``` -------------------------------- ### Send Individual Email via Microsoft Graph API - C# Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt This C# code snippet demonstrates how to send a single email message using the Office365MailSender class. It requires configuration of sender profile details, including Tenant ID, Client ID, Client Secret, and scopes. The message content can be provided in HTML or plain text. Error handling for Microsoft Graph API errors and general exceptions is included. ```csharp using Progress.Sitefinity.Office365.MailSender.Notifications; using Progress.Sitefinity.Office365.Mail.Sender.Configuration; using Progress.Sitefinity.Office365.Mail.Sender.Model; using Telerik.Sitefinity.Services.Notifications; // Configuration setup var profile = new Office365SenderProfileElement(null) { TenantId = "12345678-1234-1234-1234-123456789abc", ClientId = "87654321-4321-4321-4321-abcdef123456", ClientSecret = "your-client-secret-value-here", Scopes = "https://graph.microsoft.com/.default", DefaultSenderEmailAddress = "notifications@company.com", DefaultSenderName = "Company Notifications" }; // Create sender instance var mailSender = new Office365MailSender(profile); // Create message var messageInfo = new MessageInfo(messageTemplate, "sender@company.com", "Sender Name") { Subject = "Welcome to our platform", BodyHtml = "

Hello!

Welcome to our service.

", PlainTextVersion = "Hello! Welcome to our service.", IsHtml = true }; // Create subscriber ISubscriberRequest subscriber = new SubscriberRequest { Email = "user@example.com" }; try { // Send message SendResult result = mailSender.SendMessage(messageInfo, subscriber); if (result.Type == SendResultType.Success) { Console.WriteLine("Email sent successfully"); } } catch (ODataError odataError) { Console.WriteLine($"Graph API Error: {odataError.Error.Message} ({odataError.Error.Code})"); // Error is automatically logged to Sitefinity error log } catch (Exception ex) { Console.WriteLine($"Error sending email: {ex.Message}"); // Error is automatically logged to Sitefinity error log } finally { mailSender.Dispose(); } ``` -------------------------------- ### Define Newsletter Recipient Object Source: https://context7.com/sitefinity/sitefinity-office365-mail-sender/llms.txt Represents a recipient for a newsletter, containing their email address and name. ```csharp public class NewsletterRecipient { public string Email { get; set; } public string Name { get; set; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.