Skip to content

Commit fc1a7ac

Browse files
committed
2 parents c5ef0db + b4a0c09 commit fc1a7ac

File tree

8 files changed

+222
-0
lines changed

8 files changed

+222
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.21.0" />
12+
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.21.0" />
13+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
14+
</ItemGroup>
15+
16+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.5.33530.505
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationInsights.RedactSensitiveInformation", "ApplicationInsights.RedactSensitiveInformation.csproj", "{9D050C42-82AF-435D-9B6B-F100738B19D8}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{9D050C42-82AF-435D-9B6B-F100738B19D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{9D050C42-82AF-435D-9B6B-F100738B19D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{9D050C42-82AF-435D-9B6B-F100738B19D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{9D050C42-82AF-435D-9B6B-F100738B19D8}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {A9217409-DA3A-49F2-9C6C-B5517E73837E}
24+
EndGlobalSection
25+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Necessary using statements.
2+
using ApplicationInsights.RedactSensitiveInformation;
3+
using Microsoft.ApplicationInsights;
4+
using Microsoft.ApplicationInsights.Extensibility;
5+
using Microsoft.ApplicationInsights.WorkerService;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.Logging;
8+
using Microsoft.Extensions.Logging.ApplicationInsights;
9+
10+
// DEMO ONLY: Don't put credentials in code - use Azure Key Vault, or applicable protected configuration services.
11+
// I am using the connection string in code for clarity and avoiding unnecessary logic that distracts from the focus of the demo.
12+
const string connectionString = "InstrumentationKey=<GUID>;IngestionEndpoint=https://<endpoint>.in.applicationinsights.azure.com/;LiveEndpoint=https://<endpoint>.livediagnostics.monitor.azure.com/";
13+
14+
#region Wire-up
15+
16+
//
17+
// Wire-up.
18+
//
19+
IServiceCollection services = new ServiceCollection();
20+
21+
// Add ApplicationInsightsLoggerProvider logger.
22+
services.AddLogging(loggingBuilder => loggingBuilder.AddFilter<ApplicationInsightsLoggerProvider>("Category", LogLevel.Information));
23+
24+
// Add Application Insights logic (ApplicationInsightsTelemetryWorkerService)
25+
services.AddApplicationInsightsTelemetryWorkerService((ApplicationInsightsServiceOptions options) => options.ConnectionString = connectionString);
26+
27+
28+
// NOTE: Injecting the SensitivityRedaction initializer.
29+
services.AddSingleton<ITelemetryInitializer, SensitivityRedactionTelemetryInitializer>();
30+
31+
32+
IServiceProvider serviceProvider = services.BuildServiceProvider();
33+
34+
#endregion
35+
36+
37+
//
38+
// NOTE: Program logic to demonstrate
39+
//
40+
41+
// Get the app insights ILogger from the service provider.
42+
ILogger<Program> logger = serviceProvider.GetRequiredService<ILogger<Program>>();
43+
44+
45+
// Sending a few log messages. Some include PII, some does not.
46+
logger.LogWarning("This is a log message without PII.");
47+
logger.LogWarning("This is a log message with an e-mail: [email protected]");
48+
logger.LogWarning("This is another message with [email protected], and [email protected]");
49+
logger.LogWarning("Users access restrictions changed for: [email protected];[email protected], new access level is 'Reader' on resource '123'");
50+
51+
52+
// For demo purposes in our console app.
53+
// Used to directly flush the buffer before we quit the app.
54+
var telemetryClient = serviceProvider.GetRequiredService<TelemetryClient>();
55+
telemetryClient.Flush();
56+
Task.Delay(5000).Wait();
57+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.ApplicationInsights.Channel;
2+
using Microsoft.ApplicationInsights.DataContracts;
3+
using Microsoft.ApplicationInsights.Extensibility;
4+
using System.Text.RegularExpressions;
5+
6+
namespace ApplicationInsights.RedactSensitiveInformation
7+
{
8+
/// <summary>
9+
/// Redacts standardized sensitive information from the trace messages.
10+
/// </summary>
11+
internal class SensitivityRedactionTelemetryInitializer : ITelemetryInitializer
12+
{
13+
public void Initialize(ITelemetry t)
14+
{
15+
var traceTelemetry = t as TraceTelemetry;
16+
if (traceTelemetry != null)
17+
{
18+
// Use Regex to replace any e-mail address with a replacement string.
19+
traceTelemetry.Message = Regex.Replace(traceTelemetry.Message, @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", "[PII REDACTED]");
20+
21+
// If we don't remove this CustomDimension, the telemetry message will still contain the PII in the "OriginalFormat" property.
22+
traceTelemetry.Properties.Remove("OriginalFormat");
23+
}
24+
}
25+
}
26+
}

MicrosoftGraphEmail.Read/Program.cs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Azure.Identity;
2+
using Microsoft.Extensions.Configuration;
3+
using Microsoft.Graph;
4+
5+
namespace TZ.GraphReadEmailDemo
6+
{
7+
class Program
8+
{
9+
10+
// A simple demonstration of how to read e-mails from an Inbox using the Microsoft Graph
11+
// The code example uses the Mail.Read permission to access the current user's inbox.
12+
13+
// Read the blog post: https://zimmergren.net/reading-emails-with-microsoft-graph-using-net/
14+
15+
static void Main(string[] args)
16+
{
17+
/*
18+
* IMPORTANT:
19+
* This is demo code only.
20+
* Authentication should preferably be done using managed identity, without any credentials in code or config.
21+
* */
22+
23+
// Set up the config to load the user secrets
24+
var config = new ConfigurationBuilder()
25+
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
26+
.AddUserSecrets<Program>()
27+
.Build();
28+
29+
// Define the credentials.
30+
// Note: In your implementations of this code, please consider using managed identities, and avoid credentials in code or config.
31+
var credentials = new ClientSecretCredential(
32+
config["GraphMail:TenantId"],
33+
config["GraphMail:ClientId"],
34+
config["GraphMail:ClientSecret"],
35+
new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud });
36+
37+
// Define a new Microsoft Graph service client.
38+
GraphServiceClient _graphServiceClient = new GraphServiceClient(credentials);
39+
40+
// Get the e-mails for a specific user.
41+
var messages = _graphServiceClient.Users["[email protected]"].Messages.Request().GetAsync().Result;
42+
foreach (var message in messages)
43+
{
44+
Console.WriteLine($"{message.ReceivedDateTime?.ToString("yyyy-MM-dd HH:mm:ss")} from {message.From.EmailAddress.Address}");
45+
Console.WriteLine($"{message.Subject}");
46+
Console.WriteLine("---");
47+
}
48+
}
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<UserSecretsId>d5f6b2cb-8ebf-4359-8e25-1173da4d7b7b</UserSecretsId>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Azure.Identity" Version="1.8.0" />
13+
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
14+
<PackageReference Include="Microsoft.Graph" Version="4.49.0" />
15+
</ItemGroup>
16+
17+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.4.33122.133
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TZ.GraphReadEmailDemo", "TZ.GraphReadEmailDemo.csproj", "{A4F017E4-C11C-4EC0-879A-3718F7087AF6}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{A4F017E4-C11C-4EC0-879A-3718F7087AF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{A4F017E4-C11C-4EC0-879A-3718F7087AF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{A4F017E4-C11C-4EC0-879A-3718F7087AF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{A4F017E4-C11C-4EC0-879A-3718F7087AF6}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {2EE7D368-25CF-428A-B618-4A6EE06EE980}
24+
EndGlobalSection
25+
EndGlobal

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ This folder contains a .NET 6 console app for sending simple messages using the
5959

6060
- Read more: https://zimmergren.net/sending-e-mails-using-microsoft-graph-using-dotnet/
6161

62+
## MicrosoftGraphEmail.Read
63+
64+
This folder contains a .NET 6 app for reading e-mails using the Microsoft Graph APIs.
65+
66+
- Read more: https://zimmergren.net/reading-emails-with-microsoft-graph-using-net/
67+
6268
## AzureResourceGraph
6369

6470
In this folder, you'll find examples of Azure Resource Graph queries.

0 commit comments

Comments
 (0)