Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze tutorial maak je een python-run-function operator aan voor Lakeflow Designer die de inhoud van een DataFrame als CSV-bijlage via Gmail stuurt. In dit voorbeeld leert u hoe u op YAML gebaseerde operators bouwt die bijwerkingen uitvoeren, zoals het verzenden van meldingen of schrijven naar externe systemen. Zie Door de gebruiker gedefinieerde operators in Lakeflow Designer voor meer informatie.
Overview
De operator leest het Gmail App Password uit een Azure Databricks secret scope. Het laat het invoerdataframe ongewijzigd doorgaan naar zijn uitvoerpoort, zodat je extra operatoren stroomafwaarts kunt koppelen. Tijdens een workflow-preview wordt er geen e-mail gestuurd.
Requirements
- Een Azure Databricks-werkruimte met toegang om secret scopes te maken.
- Een Gmail-account met een Google App-wachtwoord (vereist wanneer meervoudige verificatie (MFA) is ingeschakeld).
- De Databricks CLI geïnstalleerd op uw lokale ontwikkelcomputer.
Stap 1: Geheime gegevens instellen
Sla uw Gmail-referenties op in een Azure Databricks geheim bereik, zodat de operator deze tijdens runtime kan ophalen.
Maak een geheim bereik met behulp van de Azure Databricks CLI:
databricks secrets create-scope my_email_scopeSla uw Gmail-appwachtwoord op in de scope:
databricks secrets put-secret my_email_scope gmail_app_passwordU wordt gevraagd de geheime waarde in te voeren. Plak uw Gmail-appwachtwoord en sla het op.
Stap 2: De run() functie schrijven
Voor het python-run-function operatortype is een run() functie met deze handtekening vereist:
def run(config: Dict[str, Any], inputs: Dict[str, Any], spark) -> Dict[str, Any]:
-
config: Configuratiewaarden die door de gebruiker worden verstrekt in de gebruikersinterface van Lakeflow Designer. -
inputs: Invoer-DataFrames met poortnaam als sleutel. -
spark: De actieve Spark-sessie.
De functie moet een woordenlijst met uitvoerdataframes retourneren die zijn gekoppeld aan de naam van de uitvoerpoort.
Definieer en test de functie in een notitieboekcel. Wanneer is_preview ingesteld is, slaat de functie zijn bijwerkingen over en geeft de invoer ongewijzigd terug:
from typing import Dict, Any
def run(config: Dict[str, Any], inputs: Dict[str, Any], spark) -> Dict[str, Any]:
input_df = inputs["data"]
if config.get("is_preview", False):
return {"data": input_df}
import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
sender_email = config.get("sender_email", "")
secret_scope = config.get("secret_scope", "")
secret_key = config.get("secret_key", "")
recipients_raw = config.get("recipients", "")
subject = config.get("subject", "")
body = config.get("body", "")
if not sender_email:
raise ValueError("Sender Email is required.")
if not secret_scope or not secret_key:
raise ValueError("Secret Scope and Secret Key are required.")
if not recipients_raw:
raise ValueError("At least one recipient is required.")
recipients = [r.strip() for r in recipients_raw.split(",") if r.strip()]
if not recipients:
raise ValueError("At least one valid recipient email is required.")
from pyspark.dbutils import DBUtils
dbutils = DBUtils(spark)
sender_password = dbutils.secrets.get(scope=secret_scope, key=secret_key)
pdf = input_df.toPandas()
file_path = "/tmp/designer_email_attachment.csv"
pdf.to_csv(file_path, index=False)
for recipient in recipients:
msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = recipient
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
with open(file_path, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={os.path.basename(file_path)}",
)
msg.attach(part)
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(sender_email, sender_password)
server.send_message(msg)
if os.path.exists(file_path):
os.remove(file_path)
return {"data": input_df}
Stap 3: De functie testen
Test de functie met een voorbeeld DataFrame in preview-modus, die de invoer DataFrame ongewijzigd teruggeeft en geen e-mail stuurt. Vervang <your-email@gmail.com> het met je Gmail-adres.
test_df = spark.createDataFrame(
[("Alice", 100), ("Bob", 200)],
["name", "amount"]
)
result = run(
config={
"is_preview": True,
"sender_email": "<your-email@gmail.com>",
"secret_scope": "my_email_scope",
"secret_key": "gmail_app_password",
"recipients": "alice@example.com",
"subject": "Test",
"body": "Test body"
},
inputs={"data": test_df},
spark=spark
)
result["data"].show()
Note
De secret_scope- en secret_key-waarden in de configuratie zijn de namen van de geheime scope en sleutel die je in Stap 1 hebt aangemaakt, niet het daadwerkelijke wachtwoord. De operator gebruikt deze namen om tijdens de uitvoering het wachtwoord op te halen uit de secrets van Azure Databricks.
Important
Test eerst met is_preview ingesteld op True om het pass-throughgedrag te controleren zonder e-mails te verzenden. Wanneer u klaar bent om de werkelijke e-mail te testen, stelt u deze in op is_previewFalse.
Stap 4: de YAML-definitie bouwen
Maak een bestand gmail_email_sender.yaml met de naam met de volgende inhoud:
schema: user-defined-operator-v0.1.0
id: gmail_email_sender
type: python-run-function
version: '1.0.0'
name: Gmail Email Sender
description: Sends the input DataFrame as a CSV attachment via Gmail SMTP to one or more recipients.
config:
type: object
properties:
is_preview:
type: boolean
format: is_preview
default: false
sender_email:
type: string
title: Sender Email
default: ''
examples:
- 'you@gmail.com'
x-ui:
widget: input
secret_scope:
type: string
title: Secret Scope
default: ''
examples:
- 'my_email_scope'
x-ui:
widget: input
secret_key:
type: string
title: Secret Key
default: ''
examples:
- 'gmail_app_password'
x-ui:
widget: input
recipients:
type: string
title: Recipients
default: ''
examples:
- 'alice@example.com, bob@example.com'
x-ui:
widget: textarea
rows: 2
subject:
type: string
title: Subject
default: ''
examples:
- 'Designer Output Data'
x-ui:
widget: input
body:
type: string
title: Email Body
default: "Hello,\n\nAttached is the latest data.\n\nBest,\nDatabricks Workflow"
x-ui:
widget: textarea
rows: 6
required:
- sender_email
- secret_scope
- secret_key
- recipients
- subject
additionalProperties: false
ports:
input:
- name: data
title: Input Data
mime: application/vnd.databricks.dataframe
output:
- name: data
title: Output Data
mime: application/vnd.databricks.dataframe
run_function:
type: inline
code: |
from typing import Dict, Any
def run(config: Dict[str, Any], inputs: Dict[str, Any], spark) -> Dict[str, Any]:
input_df = inputs["data"]
if config.get("is_preview", False):
return {"data": input_df}
import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
sender_email = config.get("sender_email", "")
secret_scope = config.get("secret_scope", "")
secret_key = config.get("secret_key", "")
recipients_raw = config.get("recipients", "")
subject = config.get("subject", "")
body = config.get("body", "")
if not sender_email:
raise ValueError("Sender Email is required.")
if not secret_scope or not secret_key:
raise ValueError("Secret Scope and Secret Key are required.")
if not recipients_raw:
raise ValueError("At least one recipient is required.")
recipients = [r.strip() for r in recipients_raw.split(",") if r.strip()]
if not recipients:
raise ValueError("At least one valid recipient email is required.")
from pyspark.dbutils import DBUtils
dbutils = DBUtils(spark)
sender_password = dbutils.secrets.get(scope=secret_scope, key=secret_key)
pdf = input_df.toPandas()
file_path = "/tmp/designer_email_attachment.csv"
pdf.to_csv(file_path, index=False)
for recipient in recipients:
msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = recipient
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
with open(file_path, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={os.path.basename(file_path)}",
)
msg.attach(part)
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(sender_email, sender_password)
server.send_message(msg)
if os.path.exists(file_path):
os.remove(file_path)
return {"data": input_df}
Stap 5: de operator opslaan en registreren
Sla het YAML-bestand op in uw Azure Databricks werkruimte. Voorbeeld:
/Workspace/Users/<user-name>/gmail_email_sender.yamlVoeg de operator toe aan uw
.user_defined_operators.yamlbestand:operators: - /Workspace/Users/<user-name>/gmail_email_sender.yaml
Voor meer informatie over registratieopties, zie Registreren en implementeer je operator in Lakeflow Designer.
Stap 6: Machtigingen instellen
Gebruikers die een werkstroom uitvoeren die deze operator bevat, moeten toegang hebben READ tot het geheime bereik of ze kunnen hun eigen geheime bereik en sleutelwaarden opgeven in de operatorconfiguratie. Gebruikers hebben ook leestoegang nodig tot het YAML-bestand in de werkruimte.
Toegang verlenen tot het geheime bereik:
databricks secrets put-acl my_email_scope <user-or-group> READ
Stap 7: Gebruik de operator in Lakeflow Designer
- Open bij een visuele gegevensvoorbereiding het Operators-menu in het linkerpaneel en zoek de operator Gmail Email Sender .
- Sleep de operator op het canvas en verbind een invoer ermee.
- Dubbelklik op de operator om het configuratiepaneel te openen en stel vervolgens de velden in.
- Selecteer de operator om de bijbehorende resultaten in het uitvoervenster te bekijken.
De operator heeft een invoerpoort voor uw databron en configuratievelden voor afzender-e-mail, geheime scope, geheime sleutel, ontvangers, onderwerp en hoofdtekst.