{"id":27697888,"url":"https://github.com/marcus-hooper/deployment-notification-o365","last_synced_at":"2026-01-17T16:14:07.714Z","repository":{"id":289567919,"uuid":"971683887","full_name":"marcus-hooper/deployment-notification-o365","owner":"marcus-hooper","description":"A GitHub Action for sending deployment notifications via Office 365 email using Microsoft Graph API and Azure AD.","archived":false,"fork":false,"pushed_at":"2026-01-16T19:19:34.000Z","size":184,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-16T21:13:15.921Z","etag":null,"topics":["azure","azure-ad","ci-cd","deployment","devops","email","github-actions","microsoft-graph","notifications","office365","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcus-hooper.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-23T22:45:13.000Z","updated_at":"2026-01-16T19:18:32.000Z","dependencies_parsed_at":"2025-04-25T16:37:28.016Z","dependency_job_id":null,"html_url":"https://github.com/marcus-hooper/deployment-notification-o365","commit_stats":null,"previous_names":["marcus-hooper/deployment-notification-o365"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/marcus-hooper/deployment-notification-o365","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcus-hooper%2Fdeployment-notification-o365","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcus-hooper%2Fdeployment-notification-o365/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcus-hooper%2Fdeployment-notification-o365/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcus-hooper%2Fdeployment-notification-o365/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcus-hooper","download_url":"https://codeload.github.com/marcus-hooper/deployment-notification-o365/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcus-hooper%2Fdeployment-notification-o365/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28511852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-ad","ci-cd","deployment","devops","email","github-actions","microsoft-graph","notifications","office365","python"],"created_at":"2025-04-25T16:21:44.515Z","updated_at":"2026-01-17T16:14:07.698Z","avatar_url":"https://github.com/marcus-hooper.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deployment Notification O365\n\n[![CI](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/ci.yml/badge.svg)](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/ci.yml)\n[![GitHub release](https://img.shields.io/github/v/release/marcus-hooper/deployment-notification-o365)](https://github.com/marcus-hooper/deployment-notification-o365/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![CodeQL](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/codeql.yml/badge.svg)](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/codeql.yml)\n[![Security](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/security.yml/badge.svg)](https://github.com/marcus-hooper/deployment-notification-o365/actions/workflows/security.yml)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/marcus-hooper/deployment-notification-o365/badge)](https://scorecard.dev/viewer/?uri=github.com/marcus-hooper/deployment-notification-o365)\n\nA GitHub Action that sends deployment notifications via email using Microsoft Graph API and Azure Active Directory.\n\n## Features\n\n- Sends deployment notification emails when deployments complete\n- Integrates with Microsoft Graph API for email delivery\n- Uses Azure Active Directory for secure authentication\n- Includes repository, environment, timestamp, and recent commit messages\n- Cross-platform (runs on Linux, macOS, and Windows runners)\n\n## Usage\n\n```yaml\n- name: Send Deployment Notification\n  uses: marcus-hooper/deployment-notification-o365@v1\n  env:\n    AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}\n    AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}\n    AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}\n    GITHUB_REPOSITORY: ${{ github.repository }}\n    GITHUB_ACTOR: ${{ github.actor }}\n    GITHUB_ENVIRONMENT: production\n    NOTIFICATION_TO: team@example.com, lead@example.com\n    NOTIFICATION_FROM: notifications@example.com\n```\n\n### With Commit Messages\n\nTo include recent commit messages in the notification, create a `commit_message.txt` file before calling the action:\n\n```yaml\n- name: Get recent commits\n  run: git log --oneline -5 \u003e commit_message.txt\n\n- name: Send Deployment Notification\n  uses: marcus-hooper/deployment-notification-o365@v1\n  env:\n    AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}\n    AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}\n    AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}\n    GITHUB_REPOSITORY: ${{ github.repository }}\n    GITHUB_ACTOR: ${{ github.actor }}\n    GITHUB_ENVIRONMENT: production\n    NOTIFICATION_TO: team@example.com, lead@example.com\n    NOTIFICATION_FROM: notifications@example.com\n```\n\n### Complete Workflow Example\n\nHere's a complete deployment workflow with notification:\n\n```yaml\nname: Deploy and Notify\n\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    name: Deploy Application\n    runs-on: ubuntu-latest\n    environment: production\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 5\n\n      - name: Deploy to production\n        run: |\n          # Your deployment steps here\n          echo \"Deploying application...\"\n\n      - name: Capture recent commits\n        run: git log --oneline -5 \u003e commit_message.txt\n\n      - name: Send Deployment Notification\n        uses: marcus-hooper/deployment-notification-o365@v1\n        env:\n          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}\n          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}\n          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}\n          GITHUB_REPOSITORY: ${{ github.repository }}\n          GITHUB_ACTOR: ${{ github.actor }}\n          GITHUB_ENVIRONMENT: ${{ github.environment }}\n          NOTIFICATION_TO: ${{ vars.NOTIFICATION_TO }}\n          NOTIFICATION_FROM: ${{ vars.NOTIFICATION_FROM }}\n```\n\n### Sample Email Output\n\nThe action sends a plain text email with the following format:\n\n**Subject:**\n```\nDeployment Successful: owner/repo to production on 2025-01-15 14:30:45\n```\n\n**Body:**\n```\nRepository: owner/repo\nEnvironment: production\nDeployment Time: 2025-01-15 14:30:45\nStatus: Successful\nStarted by: username\nRepository URL: https://github.com/owner/repo\n\nRecent Commit Messages:\nabc1234 Fix authentication bug\ndef5678 Add new feature\n```\n\n## Prerequisites\n\n### Azure Active Directory Application\n\n1. **Register an application** in [Azure Portal](https://portal.azure.com) \u003e Azure Active Directory \u003e App registrations \u003e New registration\n   - Name: `GitHub Deployment Notifications` (or your preference)\n   - Supported account types: Single tenant\n   - Redirect URI: Leave blank\n\n2. **Add API permissions**\n   - Go to API permissions \u003e Add a permission \u003e Microsoft Graph\n   - Select **Application permissions** (not Delegated)\n   - Search for and add `Mail.Send`\n   - Click **Grant admin consent** (requires admin privileges)\n\n3. **Create a client secret**\n   - Go to Certificates \u0026 secrets \u003e New client secret\n   - Set an expiration (recommend 12-24 months)\n   - Copy the secret value immediately (shown only once)\n\n4. **Note your credentials**\n   - **Tenant ID**: Found in Overview\n   - **Client ID**: Found in Overview (Application ID)\n   - **Client Secret**: The value you copied above\n\n### GitHub Secrets\n\nAdd the following secrets to your repository (Settings \u003e Secrets and variables \u003e Actions):\n\n| Secret | Description |\n|--------|-------------|\n| `AZURE_TENANT_ID` | Azure AD Tenant ID |\n| `AZURE_CLIENT_ID` | Azure AD Application Client ID |\n| `AZURE_CLIENT_SECRET` | Azure AD Application Client Secret |\n\n## Environment Variables\n\n### Required\n\n| Variable | Description |\n|----------|-------------|\n| `AZURE_TENANT_ID` | Azure AD Tenant ID |\n| `AZURE_CLIENT_ID` | Azure AD Application Client ID |\n| `AZURE_CLIENT_SECRET` | Azure AD Application Client Secret |\n| `GITHUB_REPOSITORY` | Repository name (owner/repo) |\n| `GITHUB_ACTOR` | User who triggered the deployment |\n| `GITHUB_ENVIRONMENT` | Deployment environment (e.g., production) |\n| `NOTIFICATION_TO` | Comma-separated recipient email addresses |\n| `NOTIFICATION_FROM` | Sender email address (must have a mailbox in your tenant) |\n\n### Optional\n\n| Input | Description |\n|-------|-------------|\n| `commit_message.txt` | File containing recent commit messages to include |\n\n## Limitations\n\n- **Plain text emails only** - HTML formatting is not supported\n- **US/Eastern timezone** - Timestamps use US/Eastern timezone; not configurable\n- **No retry logic** - Email send is attempted once; fails immediately on error\n- **Environment variables only** - Uses `env:` rather than `with:` inputs\n\n## Troubleshooting\n\n### Common Errors\n\n| Error | Cause | Solution |\n|-------|-------|----------|\n| `AADSTS7000215: Invalid client secret` | Client secret is incorrect or expired | Regenerate the client secret in Azure Portal |\n| `AADSTS700016: Application not found` | Wrong Client ID or Tenant ID | Verify IDs in Azure Portal \u003e App registrations |\n| `Authorization_RequestDenied` | Missing `Mail.Send` permission | Add permission and grant admin consent |\n| `ErrorItemNotFound` / `MailboxNotFound` | `NOTIFICATION_FROM` email doesn't exist | Use an email with a valid mailbox in your tenant |\n| `Missing required environment variable` | Env var not set or empty | Check secrets are correctly configured in GitHub |\n\n### Debug Tips\n\n1. **Check workflow logs** - Expand the \"Send notification\" step for detailed error messages\n2. **Verify Azure AD setup** - Ensure admin consent is granted (green checkmark in API permissions)\n3. **Test sender email** - The `NOTIFICATION_FROM` address must be a valid mailbox, not just an alias\n4. **Check secret expiration** - Client secrets expire; regenerate if needed\n\n## Development\n\n### Requirements\n\n- Python 3.11+\n\n### Setup\n\n```bash\n# Install dev dependencies\npip install -r requirements-dev.txt\n\n# Run tests\npytest\n\n# Run linter\nruff check .\n\n# Run type checker\nmypy send_deployment_notification.py --ignore-missing-imports\n```\n\n### Project Structure\n\n```\ndeployment-notification-o365/\n├── .github/\n│   ├── dependabot.yml\n│   ├── ISSUE_TEMPLATE/\n│   └── workflows/\n│       ├── ci.yml              # Linting, type checking, tests\n│       ├── codeql.yml          # CodeQL SAST analysis\n│       ├── security.yml        # Security scanning\n│       ├── validate.yml        # action.yml validation\n│       ├── release.yml         # Version tag management\n│       └── ...\n├── tests/                      # Unit tests\n├── action.yml                  # GitHub Action definition\n├── send_deployment_notification.py\n├── requirements.txt            # Production dependencies\n├── requirements-dev.txt        # Development dependencies\n└── pyproject.toml              # Tool configuration\n```\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Check existing [issues](https://github.com/marcus-hooper/deployment-notification-o365/issues) or open a new one\n2. Fork the repository\n3. Create a feature branch (`git checkout -b feature/my-feature`)\n4. Make your changes and add tests if applicable\n5. Ensure CI passes (`ruff check .`, `pytest`)\n6. Submit a pull request\n\nSee the issue templates for [bug reports](.github/ISSUE_TEMPLATE/bug_report.md) and [feature requests](.github/ISSUE_TEMPLATE/feature_request.md).\n\n## Security\n\nSee [SECURITY.md](SECURITY.md) for security policy and best practices.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcus-hooper%2Fdeployment-notification-o365","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcus-hooper%2Fdeployment-notification-o365","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcus-hooper%2Fdeployment-notification-o365/lists"}