Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dcc23ff
fix: pre=Refactor mod
DrIOSX Feb 25, 2025
7226b69
Fix: Mail group creation function
DrIOSX Feb 25, 2025
920b366
format: fix formatting
DrIOSX Feb 25, 2025
389eafd
update: Initialize module to continue on newer module versions
DrIOSX Feb 28, 2025
bf9f4fb
docs: Update changelog
DrIOSX Feb 28, 2025
266a57f
fix: pattern validation for company to include numbers
DrIOSX Feb 28, 2025
2f68af9
fix: pattern validation for company to include numbers
DrIOSX Feb 28, 2025
ff7b985
docs: Update changelog
DrIOSX Feb 28, 2025
fee048d
fix: formatting
DrIOSX Feb 28, 2025
713a6bc
add: connect-exchangeonline to group creation function
DrIOSX Feb 28, 2025
7224777
format: fix output formatting
DrIOSX Feb 28, 2025
25c94b9
Still need connection info formatting
DrIOSX Feb 28, 2025
386d6e6
fix: formatting and error handling
DrIOSX Mar 1, 2025
6634ef3
docs: Update changelog
DrIOSX Mar 1, 2025
1443c43
format: format output and voids
DrIOSX Mar 1, 2025
e40b3ed
fix: Function name
DrIOSX Mar 1, 2025
7785c02
format: Output formatting
DrIOSX Mar 1, 2025
16629e3
fix: function names
DrIOSX Mar 2, 2025
80bc268
docs: format docs
DrIOSX Mar 2, 2025
57ce7f3
add: output type to private function
DrIOSX Mar 2, 2025
70201b1
docs: update CHANGELOG
DrIOSX Mar 2, 2025
0037eaa
add: refactor app registration function
DrIOSX Mar 2, 2025
318490e
docs: add comment block
DrIOSX Mar 2, 2025
5f9902a
fix: refactor functions
DrIOSX Mar 2, 2025
12efeef
fix: refactor functions
DrIOSX Mar 2, 2025
84abb8a
fix: update audit function
DrIOSX Mar 2, 2025
546fd23
fix: refactor rc prior to additional scenarios
DrIOSX Mar 3, 2025
5c29408
fix: consolidate functions
DrIOSX Mar 3, 2025
5d79a3f
fix: consolidate functions
DrIOSX Mar 3, 2025
2bcb37c
add: MEMPolicyManager scenario
DrIOSX Mar 3, 2025
336f786
fix: formatting
DrIOSX Mar 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ markdownissues.txt
node_modules
package-lock.json
func.ps1
GetMGApplicationCertificateAndSecretExpiration.ps1
GetMGApplicationCertificateAndSecretExpiration.ps1
test1.ps1
testitem.txt
testitem.zip
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add support for newer versions of each module.
- Add support for numbers in pattern for app prefix.

### Fixed

- Fixed approved verb for main public function.
- Some Error handling improvements.
- Function names are now more consistent with approved verbs.
- Refactored code to improve readability.
- Consolidated functions to reduce complexity.
- Minor Change to README.md.

## [0.1.0] - 2023-07-15

### Added

- Add support for multiple attachments
- Release to public.

## [0.1.0-preview0001] - 2023-07-15

### Added
Expand Down
37 changes: 30 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
# GraphEmailApp
# GraphEmailApp Module Functions

A module for creating a graphemail app
## Connect-ToMGGraph

## Make it yours
Connects to Microsoft Graph and Exchange Online.

---
Generated with Plaster and the SampleModule template
- **Permissions**: Application.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, Directory.ReadWrite.All.
- **Modules**: Microsoft.Graph, ExchangeOnlineManagement, SecretManagement modules.
- **User Interaction**: Requires key press prompts.
- **Outputs**: Connection established, no direct output.

## Publish-GraphEmailApp

This is a sample Readme
Deploys Microsoft Graph Email app with app-only authentication.

## Make it yours
- **Parameters**: AppPrefix, CertThumbprint (optional), AuthorizedSenderUserName, MailEnabledSendingGroup.
- **Permissions**: Administrator-level for app and Exchange Online access.
- **Requirements**: Internet connectivity, mail-enabled security group in Exchange Online.
- **Outputs**: Custom object with AppId, CertThumbprint, TenantID, CertExpires.

## Initialize-GraphEmailAppCert

Retrieves or creates a new certificate.

- **Parameters**: CertThumbprint (optional), AppName.
- **Permissions**: Certificate store access.
- **Outputs**: Custom object with certificate details.

## Send-GraphAppEmail

Sends an email via Microsoft Graph API.

- **Parameters**: AppName, To, FromAddress, Subject, EmailBody, AttachmentPath (optional).
- **Modules**: Microsoft.Graph, MSAL.PS.
- **Requirements**: AppName with necessary permissions and configurations.
- **Outputs**: Email sent, no direct output.
20 changes: 20 additions & 0 deletions source/Private/ConvertTo-ParameterSplat.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function ConvertTo-ParameterSplat {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[PSObject]$InputObject
)
process {
$splatScript = "`$params = @{`n"
$InputObject.psobject.Properties | ForEach-Object {
$value = $_.Value
if ($value -is [string]) {
$value = "`"$value`""
}
$splatScript += " $($_.Name) = $value`n"
}
$splatScript += "}"
Write-Output $splatScript
}
}
95 changes: 0 additions & 95 deletions source/Private/Get-AppSecret.ps1

This file was deleted.

66 changes: 0 additions & 66 deletions source/Private/Get-GraphEmailAppConfig.ps1

This file was deleted.

104 changes: 104 additions & 0 deletions source/Private/Initialize-GraphAppRegistration.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
function Initialize-GraphAppRegistration {
[CmdletBinding()]
param(
[Parameter(
Mandatory = $true,
HelpMessage = 'The App Registration object.'
)]
$AppRegistration,
[Parameter(
Mandatory = $true,
HelpMessage = 'The Graph Service Principal Id.'
)]
[string]$GraphServicePrincipalId,
[Parameter(
Mandatory = $true,
HelpMessage = 'The Azure context.'
)]
$Context,
[Parameter(
Mandatory = $false,
HelpMessage = 'One or more OAuth2 scopes to grant. Defaults to Mail.Send.'
)]
[string[]]$Scopes = @('Mail.Send'),
[Parameter(
Mandatory = $false,
HelpMessage = 'Auth method (placeholder). Currently only "Certificate" is used.'
)]
[ValidateSet('Certificate','ClientSecret','ManagedIdentity','None')]
[string]$AuthMethod = 'Certificate',
[Parameter(
Mandatory = $false,
HelpMessage = 'Certificate thumbprint if using Certificate-based auth.'
)]
[string]$CertThumbprint
)
begin {
if (-not $script:LogString) {
Write-AuditLog -Start
}
else {
Write-AuditLog -BeginFunction
}
Write-AuditLog '###############################################'
if ($AuthMethod -eq 'Certificate' -and -not $CertThumbprint) {
throw "CertThumbprint is required when AuthMethod is 'Certificate'."
}
}
process {
try {
# 1. If using certificate auth, retrieve the certificate
$Cert = $null
if ($AuthMethod -eq 'Certificate') {
Write-AuditLog "Retrieving certificate with thumbprint $CertThumbprint."
$Cert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Thumbprint -eq $CertThumbprint }
if (-not $Cert) {
throw "Certificate with thumbprint $CertThumbprint not found in Cert:\CurrentUser\My."
}
}
# 2. Create a Service Principal for the app (if not existing).
Write-AuditLog "Creating service principal for app with AppId $($AppRegistration.AppId)."
[void](New-MgServicePrincipal -AppId $AppRegistration.AppId -AdditionalProperties @{})
# 3. Get the client Service Principal for the created app.
$ClientSp = Get-MgServicePrincipal -Filter "appId eq '$($AppRegistration.AppId)'"
if (-not $ClientSp) {
Write-AuditLog "Client service principal not found for $($AppRegistration.AppId)." -Severity Error
throw "Unable to find client service principal."
}
# 4. Combine all scopes into a single space-delimited string
$combinedScopes = $Scopes -join ' '
Write-AuditLog "Granting the following scope(s) to Service Principal $($ClientSp.DisplayName): $combinedScopes"
$Params = @{
ClientId = $ClientSp.Id
ConsentType = 'AllPrincipals'
ResourceId = $GraphServicePrincipalId
Scope = $combinedScopes
}
[void](New-MgOauth2PermissionGrant -BodyParameter $Params -Confirm:$false)
# 5. Build the admin consent URL
$adminConsentUrl = 'https://login.microsoftonline.com/' + $Context.TenantId + '/adminconsent?client_id=' + $AppRegistration.AppId
Write-Verbose 'Please go to the following URL in your browser to provide admin consent:' -Verbose
Write-Host $adminConsentUrl -ForegroundColor DarkGray
Write-Verbose 'After providing admin consent, you can use the following command for certificate-based auth:' -Verbose
if ($AuthMethod -eq 'Certificate') {
$connectGraph = 'Connect-MgGraph -ClientId "' + $AppRegistration.AppId + '" -TenantId "' +
$Context.TenantId + '" -CertificateName "' + $Cert.SubjectName.Name + '"'
Write-Host "`n$connectGraph`n" -ForegroundColor DarkGreen
}
else {
# Placeholder for other auth methods
Write-Host "Future logic for $AuthMethod auth can go here."
}
}
catch {
$line = $_.InvocationInfo.Line
$lineNum = $_.InvocationInfo.ScriptLineNumber
throw [System.Management.Automation.RuntimeException]::new(
"Error in $($MyInvocation.MyCommand.Name) at line $lineNum`:`n'$line' - $($_.Exception.Message)",
$_.Exception
)
}
Write-AuditLog -EndFunction
}
end {}
}
Loading